mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-22 11:38:57 +00:00
Onboarding: saving credentials to Keychain after account creation
Closes: #17085
This commit is contained in:
parent
c9ba6a25d6
commit
cf2c221c02
@ -543,7 +543,8 @@ proc finishAppLoading*(self: AppController) =
|
|||||||
self.startupModule = nil
|
self.startupModule = nil
|
||||||
|
|
||||||
if not self.onboardingModule.isNil:
|
if not self.onboardingModule.isNil:
|
||||||
self.onboardingModule.onAppLoaded()
|
let account = self.accountsService.getLoggedInAccount()
|
||||||
|
self.onboardingModule.onAppLoaded(account.keyUid)
|
||||||
self.onboardingModule = nil
|
self.onboardingModule = nil
|
||||||
|
|
||||||
self.mainModule.checkAndPerformProfileMigrationIfNeeded()
|
self.mainModule.checkAndPerformProfileMigrationIfNeeded()
|
||||||
|
@ -10,7 +10,7 @@ import app/modules/onboarding/post_onboarding/task
|
|||||||
method delete*(self: AccessInterface) {.base.} =
|
method delete*(self: AccessInterface) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method onAppLoaded*(self: AccessInterface) {.base.} =
|
method onAppLoaded*(self: AccessInterface, keyUid: string) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method onNodeLogin*(self: AccessInterface, error: string, account: AccountDto, settings: SettingsDto) {.base.} =
|
method onNodeLogin*(self: AccessInterface, error: string, account: AccountDto, settings: SettingsDto) {.base.} =
|
||||||
|
@ -65,8 +65,8 @@ method delete*[T](self: Module[T]) =
|
|||||||
self.viewVariant.delete
|
self.viewVariant.delete
|
||||||
self.controller.delete
|
self.controller.delete
|
||||||
|
|
||||||
method onAppLoaded*[T](self: Module[T]) =
|
method onAppLoaded*[T](self: Module[T], keyUid: string) =
|
||||||
self.view.appLoaded()
|
self.view.appLoaded(keyUid)
|
||||||
singletonInstance.engine.setRootContextProperty("onboardingModule", newQVariant())
|
singletonInstance.engine.setRootContextProperty("onboardingModule", newQVariant())
|
||||||
self.view.delete
|
self.view.delete
|
||||||
self.view = nil
|
self.view = nil
|
||||||
|
@ -33,7 +33,7 @@ QtObject:
|
|||||||
|
|
||||||
### QtSignals ###
|
### QtSignals ###
|
||||||
|
|
||||||
proc appLoaded*(self: View) {.signal.}
|
proc appLoaded*(self: View, keyUid: string) {.signal.}
|
||||||
proc accountLoginError*(self: View, error: string, wrongPassword: bool) {.signal.}
|
proc accountLoginError*(self: View, error: string, wrongPassword: bool) {.signal.}
|
||||||
|
|
||||||
### QtProperties ###
|
### QtProperties ###
|
||||||
@ -164,4 +164,4 @@ QtObject:
|
|||||||
self.delegate.loginRequested(keyUid, loginFlow, dataJson)
|
self.delegate.loginRequested(keyUid, loginFlow, dataJson)
|
||||||
|
|
||||||
proc startKeycardFactoryReset(self: View) {.slot.} =
|
proc startKeycardFactoryReset(self: View) {.slot.} =
|
||||||
self.delegate.startKeycardFactoryReset()
|
self.delegate.startKeycardFactoryReset()
|
||||||
|
@ -163,11 +163,9 @@ SplitView {
|
|||||||
signal accountLoginError(string error, bool wrongPassword)
|
signal accountLoginError(string error, bool wrongPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
biometricsAvailable: ctrlBiometrics.checked
|
keychain: keychain
|
||||||
isBiometricsLogin: ctrlTouchIdUser.checked
|
|
||||||
|
|
||||||
onBiometricsRequested: (profileId) => biometricsPopup.open()
|
biometricsAvailable: ctrlBiometrics.checked
|
||||||
onDismissBiometricsRequested: biometricsPopup.close()
|
|
||||||
|
|
||||||
onFinished: (flow, data) => {
|
onFinished: (flow, data) => {
|
||||||
console.warn("!!! ONBOARDING FINISHED; flow:", flow, "; data:", JSON.stringify(data))
|
console.warn("!!! ONBOARDING FINISHED; flow:", flow, "; data:", JSON.stringify(data))
|
||||||
@ -337,16 +335,22 @@ SplitView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BiometricsPopup {
|
KeychainMock {
|
||||||
id: biometricsPopup
|
id: keychain
|
||||||
|
|
||||||
x: root.Window.width - width
|
parent: root
|
||||||
|
|
||||||
onObtainingPasswordSuccess: {
|
readonly property alias touchIdChecked: ctrlTouchIdUser.checked
|
||||||
|
onTouchIdCheckedChanged: onboarding.keychainChanged()
|
||||||
|
|
||||||
|
function hasCredential(account) {
|
||||||
const isKeycard = onboarding.currentPage instanceof LoginScreen
|
const isKeycard = onboarding.currentPage instanceof LoginScreen
|
||||||
&& onboarding.currentPage.selectedProfileIsKeycard
|
&& onboarding.currentPage.selectedProfileIsKeycard
|
||||||
|
|
||||||
onboarding.setBiometricResponse(isKeycard ? mockDriver.pin : mockDriver.password)
|
keychain.saveCredential(account, isKeycard ? mockDriver.pin : mockDriver.password)
|
||||||
|
|
||||||
|
return touchIdChecked ? Keychain.StatusSuccess
|
||||||
|
: Keychain.StatusNotFound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ OnboardingStackView {
|
|||||||
|
|
||||||
// functions
|
// functions
|
||||||
required property var generateMnemonic
|
required property var generateMnemonic
|
||||||
required property var isBiometricsLogin
|
required property var isBiometricsLogin // (string account) => bool
|
||||||
required property var passwordStrengthScoreFunction
|
required property var passwordStrengthScoreFunction
|
||||||
required property var isSeedPhraseValid
|
required property var isSeedPhraseValid
|
||||||
required property var validateConnectionString
|
required property var validateConnectionString
|
||||||
@ -190,7 +190,8 @@ OnboardingStackView {
|
|||||||
keycardRemainingPukAttempts: root.remainingPukAttempts
|
keycardRemainingPukAttempts: root.remainingPukAttempts
|
||||||
|
|
||||||
loginAccountsModel: root.loginAccountsModel
|
loginAccountsModel: root.loginAccountsModel
|
||||||
isBiometricsLogin: root.isBiometricsLogin(loginScreen.selectedProfileKeyId)
|
isBiometricsLogin: root.biometricsAvailable &&
|
||||||
|
root.isBiometricsLogin(loginScreen.selectedProfileKeyId)
|
||||||
|
|
||||||
onBiometricsRequested: (profileId) => root.biometricsRequested(profileId)
|
onBiometricsRequested: (profileId) => root.biometricsRequested(profileId)
|
||||||
onDismissBiometricsRequested: root.dismissBiometricsRequested()
|
onDismissBiometricsRequested: root.dismissBiometricsRequested()
|
||||||
|
@ -20,9 +20,9 @@ Page {
|
|||||||
required property OnboardingStore onboardingStore
|
required property OnboardingStore onboardingStore
|
||||||
required property Keychain keychain
|
required property Keychain keychain
|
||||||
|
|
||||||
property bool biometricsAvailable: Qt.platform.os === Constants.mac
|
property bool biometricsAvailable
|
||||||
|
|
||||||
property bool networkChecksEnabled: true
|
property bool networkChecksEnabled: true
|
||||||
|
|
||||||
property alias keycardPinInfoPageDelay: onboardingFlow.keycardPinInfoPageDelay
|
property alias keycardPinInfoPageDelay: onboardingFlow.keycardPinInfoPageDelay
|
||||||
|
|
||||||
readonly property alias stack: onboardingFlow
|
readonly property alias stack: onboardingFlow
|
||||||
|
@ -7,7 +7,7 @@ import AppLayouts.Onboarding.enums 1.0
|
|||||||
QtObject {
|
QtObject {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
signal appLoaded
|
signal appLoaded(string keyUid)
|
||||||
|
|
||||||
readonly property QtObject d: StatusQUtils.QObject {
|
readonly property QtObject d: StatusQUtils.QObject {
|
||||||
id: d
|
id: d
|
||||||
|
42
ui/main.qml
42
ui/main.qml
@ -420,7 +420,7 @@ StatusWindow {
|
|||||||
Keychain {
|
Keychain {
|
||||||
service: "StatusDesktop"
|
service: "StatusDesktop"
|
||||||
|
|
||||||
id: keychain
|
id: appKeychain
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
@ -444,21 +444,42 @@ StatusWindow {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
networkChecksEnabled: true
|
networkChecksEnabled: true
|
||||||
|
|
||||||
|
// TODO: cover case when biometrics is globally disabled on mac
|
||||||
biometricsAvailable: Qt.platform.os === Constants.mac
|
biometricsAvailable: Qt.platform.os === Constants.mac
|
||||||
|
|
||||||
onboardingStore: onboardingStore
|
onboardingStore: OnboardingStore {
|
||||||
keychain: keychain
|
id: onboardingStore
|
||||||
|
|
||||||
|
onAppLoaded: {
|
||||||
|
applicationWindow.appIsReady = true
|
||||||
|
applicationWindow.storeAppState()
|
||||||
|
moveToAppMain()
|
||||||
|
}
|
||||||
|
onAccountLoginError: function (error, wrongPassword) {
|
||||||
|
onboardingLayout.stack.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keychain: appKeychain
|
||||||
|
|
||||||
onFinished: (flow, data) => {
|
onFinished: (flow, data) => {
|
||||||
const error = onboardingStore.finishOnboardingFlow(flow, data)
|
const error = onboardingStore.finishOnboardingFlow(flow, data)
|
||||||
|
|
||||||
if (error != "") {
|
if (error !== "") {
|
||||||
// We should never be here since everything should be validated already
|
// We should never be here since everything should be validated already
|
||||||
console.error("!!! ONBOARDING FINISHED WITH ERROR:", error)
|
console.error("!!! ONBOARDING FINISHED WITH ERROR:", error)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
stack.clear()
|
stack.clear()
|
||||||
stack.push(splashScreenV2, { runningProgressAnimation: true })
|
stack.push(splashScreenV2, { runningProgressAnimation: true })
|
||||||
|
|
||||||
|
if (!data.enableBiometrics)
|
||||||
|
return
|
||||||
|
|
||||||
|
onboardingStore.appLoaded.connect((keyUid) => {
|
||||||
|
appKeychain.saveCredential(keyUid, data.password || data.pin)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoginRequested: function (keyUid, method, data) {
|
onLoginRequested: function (keyUid, method, data) {
|
||||||
@ -473,19 +494,6 @@ StatusWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onCurrentPageNameChanged: Global.addCentralizedMetricIfEnabled("navigation", {viewId: currentPageName})
|
onCurrentPageNameChanged: Global.addCentralizedMetricIfEnabled("navigation", {viewId: currentPageName})
|
||||||
|
|
||||||
OnboardingStore {
|
|
||||||
id: onboardingStore
|
|
||||||
|
|
||||||
onAppLoaded: {
|
|
||||||
applicationWindow.appIsReady = true
|
|
||||||
applicationWindow.storeAppState()
|
|
||||||
moveToAppMain()
|
|
||||||
}
|
|
||||||
onAccountLoginError: function (error, wrongPassword) {
|
|
||||||
onboardingLayout.stack.pop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user