feat(@desktop/syncing): generating connection string and inserting connection string for transferring keystore files introduced
Refers to the third part of #11779
This commit is contained in:
parent
c207a4aefc
commit
85d4bfdfea
|
@ -215,7 +215,8 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
||||||
result.privacyService = privacy_service.newService(statusFoundation.events, result.settingsService,
|
result.privacyService = privacy_service.newService(statusFoundation.events, result.settingsService,
|
||||||
result.accountsService)
|
result.accountsService)
|
||||||
result.savedAddressService = saved_address_service.newService(statusFoundation.events, result.networkService, result.settingsService)
|
result.savedAddressService = saved_address_service.newService(statusFoundation.events, result.networkService, result.settingsService)
|
||||||
result.devicesService = devices_service.newService(statusFoundation.events, statusFoundation.threadpool, result.settingsService, result.accountsService)
|
result.devicesService = devices_service.newService(statusFoundation.events, statusFoundation.threadpool,
|
||||||
|
result.settingsService, result.accountsService, result.walletAccountService)
|
||||||
result.mailserversService = mailservers_service.newService(statusFoundation.events, statusFoundation.threadpool,
|
result.mailserversService = mailservers_service.newService(statusFoundation.events, statusFoundation.threadpool,
|
||||||
result.settingsService, result.nodeConfigurationService, statusFoundation.fleetConfiguration)
|
result.settingsService, result.nodeConfigurationService, statusFoundation.fleetConfiguration)
|
||||||
result.nodeService = node_service.newService(statusFoundation.events, result.settingsService, result.nodeConfigurationService)
|
result.nodeService = node_service.newService(statusFoundation.events, result.settingsService, result.nodeConfigurationService)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import json, tables, chronicles
|
import json, tables, sequtils, sugar, chronicles
|
||||||
import base
|
import base
|
||||||
import ../../../../app_service/service/accounts/dto/accounts
|
import app_service/service/accounts/dto/accounts
|
||||||
import ../../../../app_service/service/devices/dto/installation
|
import app_service/service/devices/dto/installation
|
||||||
import ../../../../app_service/service/devices/dto/local_pairing_event
|
import app_service/service/devices/dto/local_pairing_event
|
||||||
|
|
||||||
|
|
||||||
type LocalPairingSignal* = ref object of Signal
|
type LocalPairingSignal* = ref object of Signal
|
||||||
|
@ -11,6 +11,7 @@ type LocalPairingSignal* = ref object of Signal
|
||||||
error*: string
|
error*: string
|
||||||
accountData*: LocalPairingAccountData
|
accountData*: LocalPairingAccountData
|
||||||
installation*: InstallationDto
|
installation*: InstallationDto
|
||||||
|
transferredKeypairs*: seq[string] ## seq[keypair_key_uid]
|
||||||
|
|
||||||
proc fromEvent*(T: type LocalPairingSignal, event: JsonNode): LocalPairingSignal =
|
proc fromEvent*(T: type LocalPairingSignal, event: JsonNode): LocalPairingSignal =
|
||||||
result = LocalPairingSignal()
|
result = LocalPairingSignal()
|
||||||
|
@ -29,5 +30,7 @@ proc fromEvent*(T: type LocalPairingSignal, event: JsonNode): LocalPairingSignal
|
||||||
result.accountData = e["data"].toLocalPairingAccountData()
|
result.accountData = e["data"].toLocalPairingAccountData()
|
||||||
of EventReceivedInstallation:
|
of EventReceivedInstallation:
|
||||||
result.installation = e["data"].toInstallationDto()
|
result.installation = e["data"].toInstallationDto()
|
||||||
|
of EventReceivedKeystoreFiles:
|
||||||
|
result.transferredKeypairs = map(e["data"].getElems(), x => x.getStr())
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
|
@ -27,7 +27,7 @@ QtObject:
|
||||||
result.devicesLoadingError = false
|
result.devicesLoadingError = false
|
||||||
result.model = newModel()
|
result.model = newModel()
|
||||||
result.modelVariant = newQVariant(result.model)
|
result.modelVariant = newQVariant(result.model)
|
||||||
result.localPairingStatus = newLocalPairingStatus()
|
result.localPairingStatus = newLocalPairingStatus(PairingType.AppSync, LocalPairingMode.Receiver)
|
||||||
|
|
||||||
proc load*(self: View) =
|
proc load*(self: View) =
|
||||||
self.delegate.viewDidLoad()
|
self.delegate.viewDidLoad()
|
||||||
|
|
|
@ -69,7 +69,7 @@ QtObject:
|
||||||
result.loginAccountsModel = login_acc_model.newModel()
|
result.loginAccountsModel = login_acc_model.newModel()
|
||||||
result.loginAccountsModelVariant = newQVariant(result.loginAccountsModel)
|
result.loginAccountsModelVariant = newQVariant(result.loginAccountsModel)
|
||||||
result.remainingAttempts = -1
|
result.remainingAttempts = -1
|
||||||
result.localPairingStatus = newLocalPairingStatus()
|
result.localPairingStatus = newLocalPairingStatus(PairingType.AppSync, LocalPairingMode.Receiver)
|
||||||
|
|
||||||
signalConnect(result.currentStartupState, "backActionClicked()", result, "onBackActionClicked()", 2)
|
signalConnect(result.currentStartupState, "backActionClicked()", result, "onBackActionClicked()", 2)
|
||||||
signalConnect(result.currentStartupState, "primaryActionClicked()", result, "onPrimaryActionClicked()", 2)
|
signalConnect(result.currentStartupState, "primaryActionClicked()", result, "onPrimaryActionClicked()", 2)
|
||||||
|
|
|
@ -18,3 +18,8 @@ const asyncInputConnectionStringTask: Task = proc(argEncoded: string) {.gcsafe,
|
||||||
let arg = decode[AsyncInputConnectionStringArg](argEncoded)
|
let arg = decode[AsyncInputConnectionStringArg](argEncoded)
|
||||||
let response = status_go.inputConnectionStringForBootstrapping(arg.connectionString, arg.configJSON)
|
let response = status_go.inputConnectionStringForBootstrapping(arg.connectionString, arg.configJSON)
|
||||||
arg.finish(response)
|
arg.finish(response)
|
||||||
|
|
||||||
|
const asyncInputConnectionStringForImportingKeystoreTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||||
|
let arg = decode[AsyncInputConnectionStringArg](argEncoded)
|
||||||
|
let response = status_go.inputConnectionStringForImportingKeypairsKeystores(arg.connectionString, arg.configJSON)
|
||||||
|
arg.finish(response)
|
||||||
|
|
|
@ -6,23 +6,25 @@ import installation
|
||||||
|
|
||||||
type
|
type
|
||||||
EventType* {.pure.} = enum
|
EventType* {.pure.} = enum
|
||||||
EventUnknown = -1,
|
EventUnknown = -1
|
||||||
EventConnectionError = 0,
|
EventConnectionError
|
||||||
EventConnectionSuccess = 1,
|
EventConnectionSuccess
|
||||||
EventTransferError = 2,
|
EventTransferError
|
||||||
EventTransferSuccess = 3,
|
EventTransferSuccess
|
||||||
EventReceivedAccount = 4,
|
EventReceivedAccount
|
||||||
EventReceivedInstallation = 5
|
EventReceivedInstallation
|
||||||
EventProcessSuccess = 6,
|
EventProcessSuccess
|
||||||
EventProcessError = 7
|
EventProcessError
|
||||||
|
EventReceivedKeystoreFiles
|
||||||
|
|
||||||
type
|
type
|
||||||
Action* {.pure.} = enum
|
Action* {.pure.} = enum
|
||||||
ActionUnknown = 0
|
ActionUnknown = 0
|
||||||
ActionConnect = 1,
|
ActionConnect
|
||||||
ActionPairingAccount = 2,
|
ActionPairingAccount
|
||||||
ActionSyncDevice = 3,
|
ActionSyncDevice
|
||||||
ActionPairingInstallation = 4,
|
ActionPairingInstallation
|
||||||
|
ActionKeystoreFilesTransfer
|
||||||
|
|
||||||
type
|
type
|
||||||
LocalPairingAccountData* = ref object
|
LocalPairingAccountData* = ref object
|
||||||
|
@ -38,6 +40,7 @@ type
|
||||||
error*: string
|
error*: string
|
||||||
accountData*: LocalPairingAccountData
|
accountData*: LocalPairingAccountData
|
||||||
installation*: InstallationDto
|
installation*: InstallationDto
|
||||||
|
transferredKeypairs*: seq[string] ## seq[keypair_key_uid]
|
||||||
|
|
||||||
proc parse*(self: string): EventType =
|
proc parse*(self: string): EventType =
|
||||||
case self:
|
case self:
|
||||||
|
@ -57,6 +60,8 @@ proc parse*(self: string): EventType =
|
||||||
return EventReceivedAccount
|
return EventReceivedAccount
|
||||||
of "received-installation":
|
of "received-installation":
|
||||||
return EventReceivedInstallation
|
return EventReceivedInstallation
|
||||||
|
of "received-keystore-files":
|
||||||
|
return EventReceivedKeystoreFiles
|
||||||
else:
|
else:
|
||||||
return EventUnknown
|
return EventUnknown
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,11 @@ import ../../accounts/dto/accounts
|
||||||
import installation
|
import installation
|
||||||
import local_pairing_event
|
import local_pairing_event
|
||||||
|
|
||||||
|
type
|
||||||
|
PairingType* {.pure.} = enum
|
||||||
|
AppSync = 0
|
||||||
|
KeypairSync
|
||||||
|
|
||||||
type
|
type
|
||||||
LocalPairingState* {.pure.} = enum
|
LocalPairingState* {.pure.} = enum
|
||||||
Idle = 0
|
Idle = 0
|
||||||
|
@ -18,29 +23,25 @@ type
|
||||||
|
|
||||||
type
|
type
|
||||||
LocalPairingStatus* = ref object of Args
|
LocalPairingStatus* = ref object of Args
|
||||||
|
pairingType*: PairingType
|
||||||
mode*: LocalPairingMode
|
mode*: LocalPairingMode
|
||||||
state*: LocalPairingState
|
state*: LocalPairingState
|
||||||
account*: AccountDto
|
account*: AccountDto
|
||||||
password*: string
|
password*: string
|
||||||
chatKey*: string
|
chatKey*: string
|
||||||
installation*: InstallationDto
|
installation*: InstallationDto
|
||||||
|
transferredKeypairs*: seq[string] ## seq[keypair_key_uid]
|
||||||
error*: string
|
error*: string
|
||||||
|
|
||||||
proc reset*(self: LocalPairingStatus) =
|
|
||||||
self.mode = LocalPairingMode.Idle
|
|
||||||
self.state = LocalPairingState.Idle
|
|
||||||
self.error = ""
|
|
||||||
self.installation = InstallationDto()
|
|
||||||
|
|
||||||
proc setup(self: LocalPairingStatus) =
|
|
||||||
self.reset()
|
|
||||||
|
|
||||||
proc delete*(self: LocalPairingStatus) =
|
proc delete*(self: LocalPairingStatus) =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc newLocalPairingStatus*(): LocalPairingStatus =
|
proc newLocalPairingStatus*(pairingType: PairingType, mode: LocalPairingMode): LocalPairingStatus =
|
||||||
new(result, delete)
|
new(result, delete)
|
||||||
result.setup()
|
result.pairingType = pairingType
|
||||||
|
result.mode = mode
|
||||||
|
result.state = LocalPairingState.Idle
|
||||||
|
result.installation = InstallationDto()
|
||||||
|
|
||||||
proc update*(self: LocalPairingStatus, data: LocalPairingEventArgs) =
|
proc update*(self: LocalPairingStatus, data: LocalPairingEventArgs) =
|
||||||
|
|
||||||
|
@ -54,6 +55,8 @@ proc update*(self: LocalPairingStatus, data: LocalPairingEventArgs) =
|
||||||
self.chatKey = data.accountData.chatKey
|
self.chatKey = data.accountData.chatKey
|
||||||
of EventReceivedInstallation:
|
of EventReceivedInstallation:
|
||||||
self.installation = data.installation
|
self.installation = data.installation
|
||||||
|
of EventReceivedKeystoreFiles:
|
||||||
|
self.transferredKeypairs = data.transferredKeypairs
|
||||||
of EventConnectionError:
|
of EventConnectionError:
|
||||||
self.state = LocalPairingState.Error
|
self.state = LocalPairingState.Error
|
||||||
of EventTransferError:
|
of EventTransferError:
|
||||||
|
@ -67,15 +70,19 @@ proc update*(self: LocalPairingStatus, data: LocalPairingEventArgs) =
|
||||||
return
|
return
|
||||||
|
|
||||||
# Detect finished state
|
# Detect finished state
|
||||||
if (self.mode == LocalPairingMode.Sender and
|
if self.mode == LocalPairingMode.Sender and
|
||||||
data.eventType == EventProcessSuccess and
|
data.eventType == EventProcessSuccess:
|
||||||
data.action == ActionPairingInstallation):
|
if self.pairingType == PairingType.AppSync and
|
||||||
self.state = LocalPairingState.Finished
|
data.action == ActionPairingInstallation or
|
||||||
|
self.pairingType == PairingType.KeypairSync:
|
||||||
|
self.state = LocalPairingState.Finished
|
||||||
|
|
||||||
if (self.mode == LocalPairingMode.Receiver and
|
if self.mode == LocalPairingMode.Receiver and
|
||||||
data.eventType == EventTransferSuccess and
|
data.eventType == EventTransferSuccess:
|
||||||
data.action == ActionPairingInstallation):
|
if self.pairingType == PairingType.AppSync and
|
||||||
self.state = LocalPairingState.Finished
|
data.action == ActionPairingInstallation or
|
||||||
|
self.pairingType == PairingType.KeypairSync:
|
||||||
|
self.state = LocalPairingState.Finished
|
||||||
|
|
||||||
if self.state == LocalPairingState.Finished:
|
if self.state == LocalPairingState.Finished:
|
||||||
return
|
return
|
||||||
|
|
|
@ -8,6 +8,7 @@ import ./dto/local_pairing_status
|
||||||
|
|
||||||
import app_service/service/settings/service as settings_service
|
import app_service/service/settings/service as settings_service
|
||||||
import app_service/service/accounts/service as accounts_service
|
import app_service/service/accounts/service as accounts_service
|
||||||
|
import app_service/service/wallet_account/service as wallet_account_service
|
||||||
|
|
||||||
import app/global/global_singleton
|
import app/global/global_singleton
|
||||||
import app/core/[main]
|
import app/core/[main]
|
||||||
|
@ -55,23 +56,26 @@ QtObject:
|
||||||
threadpool: ThreadPool
|
threadpool: ThreadPool
|
||||||
settingsService: settings_service.Service
|
settingsService: settings_service.Service
|
||||||
accountsService: accounts_service.Service
|
accountsService: accounts_service.Service
|
||||||
|
walletAccountService: wallet_account_service.Service
|
||||||
localPairingStatus: LocalPairingStatus
|
localPairingStatus: LocalPairingStatus
|
||||||
|
|
||||||
proc delete*(self: Service) =
|
proc delete*(self: Service) =
|
||||||
self.QObject.delete
|
self.QObject.delete
|
||||||
self.localPairingStatus.delete
|
if not self.localPairingStatus.isNil:
|
||||||
|
self.localPairingStatus.delete
|
||||||
|
|
||||||
proc newService*(events: EventEmitter,
|
proc newService*(events: EventEmitter,
|
||||||
threadpool: ThreadPool,
|
threadpool: ThreadPool,
|
||||||
settingsService: settings_service.Service,
|
settingsService: settings_service.Service,
|
||||||
accountsService: accounts_service.Service): Service =
|
accountsService: accounts_service.Service,
|
||||||
new(result, delete)
|
walletAccountService: wallet_account_service.Service): Service =
|
||||||
result.QObject.setup
|
new(result, delete)
|
||||||
result.events = events
|
result.QObject.setup
|
||||||
result.threadpool = threadpool
|
result.events = events
|
||||||
result.settingsService = settingsService
|
result.threadpool = threadpool
|
||||||
result.accountsService = accountsService
|
result.settingsService = settingsService
|
||||||
result.localPairingStatus = newLocalPairingStatus()
|
result.accountsService = accountsService
|
||||||
|
result.walletAccountService = walletAccountService
|
||||||
|
|
||||||
proc updateLocalPairingStatus(self: Service, data: LocalPairingEventArgs) =
|
proc updateLocalPairingStatus(self: Service, data: LocalPairingEventArgs) =
|
||||||
self.localPairingStatus.update(data)
|
self.localPairingStatus.update(data)
|
||||||
|
@ -98,15 +102,23 @@ QtObject:
|
||||||
|
|
||||||
self.events.on(SignalType.LocalPairing.event) do(e:Args):
|
self.events.on(SignalType.LocalPairing.event) do(e:Args):
|
||||||
let signalData = LocalPairingSignal(e)
|
let signalData = LocalPairingSignal(e)
|
||||||
if not signalData.accountData.isNil and signalData.accountData.keycardPairings.len > 0:
|
if self.localPairingStatus.pairingType == PairingType.AppSync:
|
||||||
createKeycardPairingFile(signalData.accountData.keycardPairings)
|
if not signalData.accountData.isNil and signalData.accountData.keycardPairings.len > 0:
|
||||||
let data = LocalPairingEventArgs(
|
createKeycardPairingFile(signalData.accountData.keycardPairings)
|
||||||
eventType: signalData.eventType,
|
let data = LocalPairingEventArgs(
|
||||||
action: signalData.action,
|
eventType: signalData.eventType,
|
||||||
accountData: signalData.accountData,
|
action: signalData.action,
|
||||||
installation: signalData.installation,
|
accountData: signalData.accountData,
|
||||||
error: signalData.error)
|
installation: signalData.installation,
|
||||||
self.updateLocalPairingStatus(data)
|
error: signalData.error)
|
||||||
|
self.updateLocalPairingStatus(data)
|
||||||
|
elif self.localPairingStatus.pairingType == PairingType.KeypairSync:
|
||||||
|
let data = LocalPairingEventArgs(
|
||||||
|
eventType: signalData.eventType,
|
||||||
|
action: signalData.action,
|
||||||
|
error: signalData.error,
|
||||||
|
transferredKeypairs: signalData.transferredKeypairs)
|
||||||
|
self.updateLocalPairingStatus(data)
|
||||||
|
|
||||||
proc init*(self: Service) =
|
proc init*(self: Service) =
|
||||||
self.doConnect()
|
self.doConnect()
|
||||||
|
@ -185,6 +197,10 @@ QtObject:
|
||||||
self.updateLocalPairingStatus(data)
|
self.updateLocalPairingStatus(data)
|
||||||
|
|
||||||
proc validateConnectionString*(self: Service, connectionString: string): string =
|
proc validateConnectionString*(self: Service, connectionString: string): string =
|
||||||
|
if connectionString.len == 0:
|
||||||
|
result = "an empty connection string provided"
|
||||||
|
error "error", msg=result
|
||||||
|
return
|
||||||
return status_go.validateConnectionString(connectionString)
|
return status_go.validateConnectionString(connectionString)
|
||||||
|
|
||||||
proc getConnectionStringForBootstrappingAnotherDevice*(self: Service, password: string, chatKey: string): string =
|
proc getConnectionStringForBootstrappingAnotherDevice*(self: Service, password: string, chatKey: string): string =
|
||||||
|
@ -209,8 +225,7 @@ QtObject:
|
||||||
"timeout": 5 * 60 * 1000,
|
"timeout": 5 * 60 * 1000,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.localPairingStatus.reset()
|
self.localPairingStatus = newLocalPairingStatus(PairingType.AppSync, LocalPairingMode.Sender)
|
||||||
self.localPairingStatus.mode = LocalPairingMode.Sender
|
|
||||||
return status_go.getConnectionStringForBootstrappingAnotherDevice($configJSON)
|
return status_go.getConnectionStringForBootstrappingAnotherDevice($configJSON)
|
||||||
|
|
||||||
proc inputConnectionStringForBootstrapping*(self: Service, connectionString: string): string =
|
proc inputConnectionStringForBootstrapping*(self: Service, connectionString: string): string =
|
||||||
|
@ -226,8 +241,7 @@ QtObject:
|
||||||
},
|
},
|
||||||
"clientConfig": %* {}
|
"clientConfig": %* {}
|
||||||
}
|
}
|
||||||
self.localPairingStatus.reset()
|
self.localPairingStatus = newLocalPairingStatus(PairingType.AppSync, LocalPairingMode.Receiver)
|
||||||
self.localPairingStatus.mode = LocalPairingMode.Receiver
|
|
||||||
|
|
||||||
let arg = AsyncInputConnectionStringArg(
|
let arg = AsyncInputConnectionStringArg(
|
||||||
tptr: cast[ByteAddress](asyncInputConnectionStringTask),
|
tptr: cast[ByteAddress](asyncInputConnectionStringTask),
|
||||||
|
@ -237,3 +251,127 @@ QtObject:
|
||||||
configJSON: $configJSON
|
configJSON: $configJSON
|
||||||
)
|
)
|
||||||
self.threadpool.start(arg)
|
self.threadpool.start(arg)
|
||||||
|
|
||||||
|
proc validateKeyUids*(self: Service, keyUids: seq[string], validateForExport: bool): tuple[finalKeyUids: seq[string], err: string] =
|
||||||
|
if keyUids.len > 0:
|
||||||
|
for keyUid in keyUids:
|
||||||
|
let kp = self.walletAccountService.getKeypairByKeyUid(keyUid)
|
||||||
|
if kp.isNil:
|
||||||
|
result.err = "cannot resolve keypair for provided keyUid"
|
||||||
|
return
|
||||||
|
let migratedToKeycard = kp.keycards.len > 0
|
||||||
|
if migratedToKeycard or kp.keypairType == KeypairTypeProfile:
|
||||||
|
result.err = "keypair is migrated to a keycard or refers to a profile keypair"
|
||||||
|
return
|
||||||
|
if validateForExport:
|
||||||
|
if kp.getOperability() == AccountNonOperable:
|
||||||
|
result.err = "cannot export non operable keypair"
|
||||||
|
return
|
||||||
|
elif kp.getOperability() != AccountNonOperable:
|
||||||
|
result.err = "keypair is already fully or partially operable"
|
||||||
|
return
|
||||||
|
result.finalKeyUids.add(kp.keyUid)
|
||||||
|
else:
|
||||||
|
let keypairs = self.walletAccountService.getKeypairs()
|
||||||
|
for kp in keypairs:
|
||||||
|
let migratedToKeycard = kp.keycards.len > 0
|
||||||
|
if migratedToKeycard or
|
||||||
|
kp.keypairType == KeypairTypeProfile or
|
||||||
|
validateForExport and kp.getOperability() == AccountNonOperable or
|
||||||
|
not validateForExport and kp.getOperability() != AccountNonOperable:
|
||||||
|
continue
|
||||||
|
result.finalKeyUids.add(kp.keyUid)
|
||||||
|
|
||||||
|
if result.finalKeyUids.len == 0:
|
||||||
|
result.err = "there is no valid keypair"
|
||||||
|
|
||||||
|
## Providing an empty array of keyUids means generating a connection string and transferring all non operable keypairs
|
||||||
|
proc generateConnectionStringForExportingKeypairsKeystores*(self: Service, keyUids: seq[string], password: string): tuple[res: string, err: string] =
|
||||||
|
if password.len == 0:
|
||||||
|
result.err = "emtpy password provided"
|
||||||
|
error "error", msg=result.err
|
||||||
|
return
|
||||||
|
let(finalKeyUids, err) = self.validateKeyUids(keyUids, validateForExport=true)
|
||||||
|
if err.len > 0:
|
||||||
|
result.err = err
|
||||||
|
error "error", msg=err
|
||||||
|
return
|
||||||
|
|
||||||
|
let loggedInUserKeyUid = singletonInstance.userProfile.getKeyUid()
|
||||||
|
let keycardUser = singletonInstance.userProfile.getIsKeycardUser()
|
||||||
|
|
||||||
|
var finalPassword = utils.hashPassword(password)
|
||||||
|
if keycardUser:
|
||||||
|
finalPassword = password
|
||||||
|
|
||||||
|
let configJSON = %* {
|
||||||
|
"senderConfig": %* {
|
||||||
|
"keystorePath": joinPath(main_constants.ROOTKEYSTOREDIR, loggedInUserKeyUid),
|
||||||
|
"loggedInKeyUid": loggedInUserKeyUid,
|
||||||
|
"password": finalPassword,
|
||||||
|
"keypairsToExport": finalKeyUids,
|
||||||
|
},
|
||||||
|
"serverConfig": %* {
|
||||||
|
"timeout": 5 * 60 * 1000,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.localPairingStatus = newLocalPairingStatus(PairingType.KeypairSync, LocalPairingMode.Sender)
|
||||||
|
let response = status_go.getConnectionStringForExportingKeypairsKeystores($configJSON)
|
||||||
|
try:
|
||||||
|
let jsonObj = response.parseJson
|
||||||
|
if jsonObj.hasKey("error"):
|
||||||
|
return ("", jsonObj["error"].getStr)
|
||||||
|
except Exception:
|
||||||
|
return (response, "")
|
||||||
|
|
||||||
|
proc inputConnectionStringForImportingKeystoreFinished*(self: Service, responseJson: string) {.slot.} =
|
||||||
|
try:
|
||||||
|
let jsonObj = responseJson.parseJson
|
||||||
|
if jsonObj.hasKey("error") and jsonObj["error"].getStr.len == 0:
|
||||||
|
info "keystore files successfully transferred"
|
||||||
|
self.walletAccountService.updateKeypairOperabilityInLocalStoreAndNotify(self.localPairingStatus.transferredKeypairs)
|
||||||
|
return
|
||||||
|
let errorDescription = jsonObj["error"].getStr
|
||||||
|
error "failed to start transferring keystore files", errorDescription
|
||||||
|
self.events.emit(SIGNAL_IMPORTED_KEYPAIRS, KeypairsArgs(error: errorDescription))
|
||||||
|
except Exception as e:
|
||||||
|
error "unexpected error", msg=e.msg
|
||||||
|
|
||||||
|
## Providing an empty array of keyUids means expecting keystore files for all non operable keypairs to be received
|
||||||
|
proc inputConnectionStringForImportingKeypairsKeystores*(self: Service, keyUids: seq[string], connectionString: string, password: string): string =
|
||||||
|
if password.len == 0:
|
||||||
|
result = "emtpy password provided"
|
||||||
|
error "error", msg=result
|
||||||
|
return
|
||||||
|
let(finalKeyUids, err) = self.validateKeyUids(keyUids, validateForExport=false)
|
||||||
|
if err.len > 0:
|
||||||
|
result = err
|
||||||
|
error "error", msg=result
|
||||||
|
return
|
||||||
|
|
||||||
|
let loggedInUserKeyUid = singletonInstance.userProfile.getKeyUid()
|
||||||
|
let keycardUser = singletonInstance.userProfile.getIsKeycardUser()
|
||||||
|
|
||||||
|
var finalPassword = utils.hashPassword(password)
|
||||||
|
if keycardUser:
|
||||||
|
finalPassword = password
|
||||||
|
|
||||||
|
let configJSON = %* {
|
||||||
|
"receiverConfig": %* {
|
||||||
|
"keystorePath": main_constants.ROOTKEYSTOREDIR,
|
||||||
|
"loggedInKeyUid": loggedInUserKeyUid,
|
||||||
|
"password": finalPassword,
|
||||||
|
"keypairsToImport": finalKeyUids,
|
||||||
|
},
|
||||||
|
"clientConfig": %* {}
|
||||||
|
}
|
||||||
|
self.localPairingStatus = newLocalPairingStatus(PairingType.KeypairSync, LocalPairingMode.Receiver)
|
||||||
|
|
||||||
|
let arg = AsyncInputConnectionStringArg(
|
||||||
|
tptr: cast[ByteAddress](asyncInputConnectionStringForImportingKeystoreTask),
|
||||||
|
vptr: cast[ByteAddress](self.vptr),
|
||||||
|
slot: "inputConnectionStringForImportingKeystoreFinished",
|
||||||
|
connectionString: connectionString,
|
||||||
|
configJSON: $configJSON
|
||||||
|
)
|
||||||
|
self.threadpool.start(arg)
|
|
@ -1,4 +1,4 @@
|
||||||
import tables, json, strformat, strutils, chronicles
|
import tables, json, strformat, strutils, sequtils, sugar, chronicles
|
||||||
|
|
||||||
import account_dto, keycard_dto
|
import account_dto, keycard_dto
|
||||||
|
|
||||||
|
@ -73,3 +73,10 @@ proc `$`*(self: KeypairDto): string =
|
||||||
"""
|
"""
|
||||||
result &= """
|
result &= """
|
||||||
]"""
|
]"""
|
||||||
|
|
||||||
|
proc getOperability*(self: KeypairDto): string =
|
||||||
|
if self.accounts.any(x => x.operable == AccountNonOperable):
|
||||||
|
return AccountNonOperable
|
||||||
|
if self.accounts.any(x => x.operable == AccountPartiallyOperable):
|
||||||
|
return AccountPartiallyOperable
|
||||||
|
return AccountFullyOperable
|
|
@ -215,14 +215,24 @@ proc removeAccountFromLocalStoreAndNotify(self: Service, address: string, notify
|
||||||
if notify:
|
if notify:
|
||||||
self.events.emit(SIGNAL_WALLET_ACCOUNT_DELETED, AccountArgs(account: acc))
|
self.events.emit(SIGNAL_WALLET_ACCOUNT_DELETED, AccountArgs(account: acc))
|
||||||
|
|
||||||
proc updateKeypairOperabilityInLocalStoreAndNotify(self: Service, keyUid: string) =
|
proc updateKeypairOperabilityInLocalStoreAndNotify*(self: Service, importedKeyUids: seq[string]) =
|
||||||
let kp = self.getKeypairByKeyUid(keyUid)
|
var updatedKeypairs: seq[KeypairDto]
|
||||||
if kp.isNil:
|
let localKeypairs = self.getKeypairs()
|
||||||
error "there is no known keypair", keyUid=keyUid, procName="updateKeypairOperabilityInLocalStoreAndNotify"
|
for keyUid in importedKeyUids:
|
||||||
|
var foundKp: KeypairDto = nil
|
||||||
|
for kp in localKeypairs:
|
||||||
|
if keyUid == kp.keyUid:
|
||||||
|
foundKp = kp
|
||||||
|
break
|
||||||
|
if foundKp.isNil:
|
||||||
|
error "there is no known keypair", keyUid=keyUid, procName="updateKeypairOperabilityInLocalStoreAndNotify"
|
||||||
|
return
|
||||||
|
for acc in foundKp.accounts:
|
||||||
|
acc.operable = AccountFullyOperable
|
||||||
|
updatedKeypairs.add(foundKp)
|
||||||
|
if updatedKeypairs.len == 0:
|
||||||
return
|
return
|
||||||
for acc in kp.accounts:
|
self.events.emit(SIGNAL_IMPORTED_KEYPAIRS, KeypairsArgs(keypairs: updatedKeypairs))
|
||||||
acc.operable = AccountFullyOperable
|
|
||||||
self.events.emit(SIGNAL_KEYPAIR_OPERABILITY_CHANGED, KeypairArgs(keypair: kp))
|
|
||||||
|
|
||||||
proc updateAccountsPositions(self: Service) =
|
proc updateAccountsPositions(self: Service) =
|
||||||
let dbAccounts = getAccountsFromDb()
|
let dbAccounts = getAccountsFromDb()
|
||||||
|
@ -326,7 +336,7 @@ proc makePrivateKeyKeypairFullyOperable*(self: Service, keyUid, privateKey, pass
|
||||||
if not response.error.isNil:
|
if not response.error.isNil:
|
||||||
error "status-go error", procName="makePrivateKeyKeypairFullyOperable", errCode=response.error.code, errDesription=response.error.message
|
error "status-go error", procName="makePrivateKeyKeypairFullyOperable", errCode=response.error.code, errDesription=response.error.message
|
||||||
return response.error.message
|
return response.error.message
|
||||||
self.updateKeypairOperabilityInLocalStoreAndNotify(keyUid)
|
self.updateKeypairOperabilityInLocalStoreAndNotify(@[keyUid])
|
||||||
return ""
|
return ""
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error "error: ", procName="makePrivateKeyKeypairFullyOperable", errName=e.name, errDesription=e.msg
|
error "error: ", procName="makePrivateKeyKeypairFullyOperable", errName=e.name, errDesription=e.msg
|
||||||
|
@ -367,7 +377,7 @@ proc makeSeedPhraseKeypairFullyOperable*(self: Service, keyUid, mnemonic, passwo
|
||||||
if not response.error.isNil:
|
if not response.error.isNil:
|
||||||
error "status-go error", procName="makeSeedPhraseKeypairFullyOperable", errCode=response.error.code, errDesription=response.error.message
|
error "status-go error", procName="makeSeedPhraseKeypairFullyOperable", errCode=response.error.code, errDesription=response.error.message
|
||||||
return response.error.message
|
return response.error.message
|
||||||
self.updateKeypairOperabilityInLocalStoreAndNotify(keyUid)
|
self.updateKeypairOperabilityInLocalStoreAndNotify(@[keyUid])
|
||||||
return ""
|
return ""
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error "error: ", procName="makeSeedPhraseKeypairFullyOperable", errName=e.name, errDesription=e.msg
|
error "error: ", procName="makeSeedPhraseKeypairFullyOperable", errName=e.name, errDesription=e.msg
|
||||||
|
|
|
@ -19,7 +19,7 @@ const SIGNAL_WALLET_ACCOUNT_PREFERRED_SHARING_CHAINS_UPDATED* = "walletAccount/p
|
||||||
const SIGNAL_KEYPAIR_SYNCED* = "keypairSynced"
|
const SIGNAL_KEYPAIR_SYNCED* = "keypairSynced"
|
||||||
const SIGNAL_KEYPAIR_NAME_CHANGED* = "keypairNameChanged"
|
const SIGNAL_KEYPAIR_NAME_CHANGED* = "keypairNameChanged"
|
||||||
const SIGNAL_KEYPAIR_DELETED* = "keypairDeleted"
|
const SIGNAL_KEYPAIR_DELETED* = "keypairDeleted"
|
||||||
const SIGNAL_KEYPAIR_OPERABILITY_CHANGED* = "keypairOperabilityChanged"
|
const SIGNAL_IMPORTED_KEYPAIRS* = "importedKeypairs"
|
||||||
|
|
||||||
const SIGNAL_NEW_KEYCARD_SET* = "newKeycardSet"
|
const SIGNAL_NEW_KEYCARD_SET* = "newKeycardSet"
|
||||||
const SIGNAL_KEYCARD_REBUILD* = "keycardRebuild"
|
const SIGNAL_KEYCARD_REBUILD* = "keycardRebuild"
|
||||||
|
@ -43,6 +43,10 @@ type KeypairArgs* = ref object of Args
|
||||||
keyPairName*: string
|
keyPairName*: string
|
||||||
oldKeypairName*: string
|
oldKeypairName*: string
|
||||||
|
|
||||||
|
type KeypairsArgs* = ref object of Args
|
||||||
|
keypairs*: seq[KeypairDto]
|
||||||
|
error*: string
|
||||||
|
|
||||||
type KeycardArgs* = ref object of Args
|
type KeycardArgs* = ref object of Args
|
||||||
success*: bool
|
success*: bool
|
||||||
oldKeycardUid*: string
|
oldKeycardUid*: string
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0a0b5f0f320a7ed3adf53218e5b18fc41d0fbef0
|
Subproject commit f75bbc383157285d8260365e3b95def7b259e340
|
Loading…
Reference in New Issue