fix(@desktop/general): invalid pin saved to keychain when enabling biometrics on account using keycard
Fixes: #7729
This commit is contained in:
parent
ca3f82848b
commit
224fd3f42d
|
@ -95,7 +95,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface,
|
||||||
result.profileModule = profile_module.newModule(result, profileService, settingsService)
|
result.profileModule = profile_module.newModule(result, profileService, settingsService)
|
||||||
result.contactsModule = contacts_module.newModule(result, events, contactsService, chatService)
|
result.contactsModule = contacts_module.newModule(result, events, contactsService, chatService)
|
||||||
result.languageModule = language_module.newModule(result, events, languageService)
|
result.languageModule = language_module.newModule(result, events, languageService)
|
||||||
result.privacyModule = privacy_module.newModule(result, events, settingsService, privacyService, generalService)
|
result.privacyModule = privacy_module.newModule(result, events, settingsService, keychainService, privacyService, generalService)
|
||||||
result.aboutModule = about_module.newModule(result, events, aboutService)
|
result.aboutModule = about_module.newModule(result, events, aboutService)
|
||||||
result.advancedModule = advanced_module.newModule(result, events, settingsService, stickersService, nodeConfigurationService)
|
result.advancedModule = advanced_module.newModule(result, events, settingsService, stickersService, nodeConfigurationService)
|
||||||
result.devicesModule = devices_module.newModule(result, events, settingsService, devicesService)
|
result.devicesModule = devices_module.newModule(result, events, settingsService, devicesService)
|
||||||
|
|
|
@ -1,35 +1,68 @@
|
||||||
import io_interface
|
import io_interface
|
||||||
|
import uuids
|
||||||
|
|
||||||
|
import ../../../../../constants as main_constants
|
||||||
|
import ../../../../global/global_singleton
|
||||||
import ../../../../core/eventemitter
|
import ../../../../core/eventemitter
|
||||||
import ../../../../../app_service/service/settings/service as settings_service
|
import ../../../../../app_service/service/settings/service as settings_service
|
||||||
|
import ../../../../../app_service/service/keychain/service as keychain_service
|
||||||
import ../../../../../app_service/service/privacy/service as privacy_service
|
import ../../../../../app_service/service/privacy/service as privacy_service
|
||||||
import ../../../../../app_service/service/general/service as general_service
|
import ../../../../../app_service/service/general/service as general_service
|
||||||
|
import ../../../shared_modules/keycard_popup/io_interface as keycard_shared_module
|
||||||
|
|
||||||
|
const UNIQUE_PRIVACY_SECTION_MODULE_AUTH_IDENTIFIER* = "PrivacySectionModule-Authentication"
|
||||||
|
|
||||||
type
|
type
|
||||||
Controller* = ref object of RootObj
|
Controller* = ref object of RootObj
|
||||||
delegate: io_interface.AccessInterface
|
delegate: io_interface.AccessInterface
|
||||||
events: EventEmitter
|
events: EventEmitter
|
||||||
settingsService: settings_service.Service
|
settingsService: settings_service.Service
|
||||||
|
keychainService: keychain_service.Service
|
||||||
privacyService: privacy_service.Service
|
privacyService: privacy_service.Service
|
||||||
generalService: general_service.Service
|
generalService: general_service.Service
|
||||||
|
keychainConnectionIds: seq[UUID]
|
||||||
|
|
||||||
proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter,
|
proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter,
|
||||||
|
|
||||||
settingsService: settings_service.Service,
|
settingsService: settings_service.Service,
|
||||||
|
keychainService: keychain_service.Service,
|
||||||
privacyService: privacy_service.Service,
|
privacyService: privacy_service.Service,
|
||||||
generalService: general_service.Service): Controller =
|
generalService: general_service.Service): Controller =
|
||||||
result = Controller()
|
result = Controller()
|
||||||
result.delegate = delegate
|
result.delegate = delegate
|
||||||
result.events = events
|
result.events = events
|
||||||
result.settingsService = settingsService
|
result.settingsService = settingsService
|
||||||
|
result.keychainService = keychainService
|
||||||
result.privacyService = privacyService
|
result.privacyService = privacyService
|
||||||
result.generalService = generalService
|
result.generalService = generalService
|
||||||
|
|
||||||
proc delete*(self: Controller) =
|
proc delete*(self: Controller) =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
proc disconnectKeychain*(self: Controller) =
|
||||||
|
for id in self.keychainConnectionIds:
|
||||||
|
self.events.disconnect(id)
|
||||||
|
self.keychainConnectionIds = @[]
|
||||||
|
|
||||||
|
proc connectKeychain*(self: Controller) =
|
||||||
|
var handlerId = self.events.onWithUUID(SIGNAL_KEYCHAIN_SERVICE_SUCCESS) do(e:Args):
|
||||||
|
let args = KeyChainServiceArg(e)
|
||||||
|
self.disconnectKeychain()
|
||||||
|
self.delegate.onStoreToKeychainSuccess(args.data)
|
||||||
|
self.keychainConnectionIds.add(handlerId)
|
||||||
|
|
||||||
|
handlerId = self.events.onWithUUID(SIGNAL_KEYCHAIN_SERVICE_ERROR) do(e:Args):
|
||||||
|
let args = KeyChainServiceArg(e)
|
||||||
|
self.disconnectKeychain()
|
||||||
|
self.delegate.onStoreToKeychainError(args.errDescription, args.errType)
|
||||||
|
self.keychainConnectionIds.add(handlerId)
|
||||||
|
|
||||||
proc init*(self: Controller) =
|
proc init*(self: Controller) =
|
||||||
|
self.events.on(SIGNAL_SHARED_KEYCARD_MODULE_USER_AUTHENTICATED) do(e: Args):
|
||||||
|
let args = SharedKeycarModuleArgs(e)
|
||||||
|
if args.uniqueIdentifier != UNIQUE_PRIVACY_SECTION_MODULE_AUTH_IDENTIFIER:
|
||||||
|
return
|
||||||
|
self.delegate.onUserAuthenticated(args.pin, args.password, args.keyUid)
|
||||||
|
|
||||||
self.events.on(SIGNAL_MNEMONIC_REMOVAL) do(e: Args):
|
self.events.on(SIGNAL_MNEMONIC_REMOVAL) do(e: Args):
|
||||||
self.delegate.onMnemonicUpdated()
|
self.delegate.onMnemonicUpdated()
|
||||||
|
|
||||||
|
@ -67,3 +100,30 @@ proc validatePassword*(self: Controller, password: string): bool =
|
||||||
method getPasswordStrengthScore*(self: Controller, password, userName: string): int =
|
method getPasswordStrengthScore*(self: Controller, password, userName: string): int =
|
||||||
return self.generalService.getPasswordStrengthScore(password, userName)
|
return self.generalService.getPasswordStrengthScore(password, userName)
|
||||||
|
|
||||||
|
proc storeToKeychain*(self: Controller, data: string) =
|
||||||
|
let myName = singletonInstance.userProfile.getName()
|
||||||
|
let value = singletonInstance.localAccountSettings.getStoreToKeychainValue()
|
||||||
|
if not main_constants.IS_MACOS or # Dealing with Keychain is the MacOS only feature
|
||||||
|
data.len == 0 or
|
||||||
|
value == LS_VALUE_STORE or
|
||||||
|
myName.len == 0:
|
||||||
|
self.delegate.onStoreToKeychainError("", "")
|
||||||
|
return
|
||||||
|
self.connectKeychain()
|
||||||
|
self.keychainService.storeData(myName, data)
|
||||||
|
|
||||||
|
proc removeFromKeychain*(self: Controller, key: string) =
|
||||||
|
let value = singletonInstance.localAccountSettings.getStoreToKeychainValue()
|
||||||
|
if not main_constants.IS_MACOS or # Dealing with Keychain is the MacOS only feature
|
||||||
|
key.len == 0 or
|
||||||
|
value != LS_VALUE_STORE:
|
||||||
|
self.delegate.onStoreToKeychainError("", "")
|
||||||
|
return
|
||||||
|
self.connectKeychain()
|
||||||
|
self.keychainService.tryToDeleteData(key)
|
||||||
|
|
||||||
|
proc authenticateLoggedInUser*(self: Controller) =
|
||||||
|
var data = SharedKeycarModuleAuthenticationArgs(uniqueIdentifier: UNIQUE_PRIVACY_SECTION_MODULE_AUTH_IDENTIFIER)
|
||||||
|
if singletonInstance.userProfile.getIsKeycardUser():
|
||||||
|
data.keyUid = singletonInstance.userProfile.getKeyUid()
|
||||||
|
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data)
|
|
@ -58,3 +58,18 @@ method validatePassword*(self: AccessInterface, password: string): bool {.base.}
|
||||||
|
|
||||||
method getPasswordStrengthScore*(self: AccessInterface, password: string): int {.base.} =
|
method getPasswordStrengthScore*(self: AccessInterface, password: string): int {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method onStoreToKeychainError*(self: AccessInterface, errorDescription: string, errorType: string) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method onStoreToKeychainSuccess*(self: AccessInterface, data: string) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method tryStoreToKeyChain*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method tryRemoveFromKeyChain*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method onUserAuthenticated*(self: AccessInterface, pin: string, password: string, keyUid: string) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
|
@ -7,11 +7,17 @@ import ../io_interface as delegate_interface
|
||||||
|
|
||||||
import ../../../../core/eventemitter
|
import ../../../../core/eventemitter
|
||||||
import ../../../../../app_service/service/settings/service as settings_service
|
import ../../../../../app_service/service/settings/service as settings_service
|
||||||
|
import ../../../../../app_service/service/keychain/service as keychain_service
|
||||||
import ../../../../../app_service/service/privacy/service as privacy_service
|
import ../../../../../app_service/service/privacy/service as privacy_service
|
||||||
import ../../../../../app_service/service/general/service as general_service
|
import ../../../../../app_service/service/general/service as general_service
|
||||||
|
|
||||||
export io_interface
|
export io_interface
|
||||||
|
|
||||||
|
type
|
||||||
|
KeychainActivityReason {.pure.} = enum
|
||||||
|
StoreTo = 0
|
||||||
|
RemoveFrom
|
||||||
|
|
||||||
type
|
type
|
||||||
Module* = ref object of io_interface.AccessInterface
|
Module* = ref object of io_interface.AccessInterface
|
||||||
delegate: delegate_interface.AccessInterface
|
delegate: delegate_interface.AccessInterface
|
||||||
|
@ -19,9 +25,11 @@ type
|
||||||
view: View
|
view: View
|
||||||
viewVariant: QVariant
|
viewVariant: QVariant
|
||||||
moduleLoaded: bool
|
moduleLoaded: bool
|
||||||
|
keychainActivityReason: KeychainActivityReason
|
||||||
|
|
||||||
proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter,
|
proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter,
|
||||||
settingsService: settings_service.Service,
|
settingsService: settings_service.Service,
|
||||||
|
keychainService: keychain_service.Service,
|
||||||
privacyService: privacy_service.Service,
|
privacyService: privacy_service.Service,
|
||||||
generalService: general_service.Service):
|
generalService: general_service.Service):
|
||||||
Module =
|
Module =
|
||||||
|
@ -29,7 +37,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitt
|
||||||
result.delegate = delegate
|
result.delegate = delegate
|
||||||
result.view = newView(result)
|
result.view = newView(result)
|
||||||
result.viewVariant = newQVariant(result.view)
|
result.viewVariant = newQVariant(result.view)
|
||||||
result.controller = controller.newController(result, events, settingsService, privacyService, generalService)
|
result.controller = controller.newController(result, events, settingsService, keychainService, privacyService, generalService)
|
||||||
result.moduleLoaded = false
|
result.moduleLoaded = false
|
||||||
|
|
||||||
method delete*(self: Module) =
|
method delete*(self: Module) =
|
||||||
|
@ -85,3 +93,28 @@ method validatePassword*(self: Module, password: string): bool =
|
||||||
|
|
||||||
method getPasswordStrengthScore*(self: Module, password: string): int =
|
method getPasswordStrengthScore*(self: Module, password: string): int =
|
||||||
return self.controller.getPasswordStrengthScore(password, singletonInstance.userProfile.getUsername())
|
return self.controller.getPasswordStrengthScore(password, singletonInstance.userProfile.getUsername())
|
||||||
|
|
||||||
|
method onStoreToKeychainError*(self: Module, errorDescription: string, errorType: string) =
|
||||||
|
self.view.emitStoreToKeychainError(errorDescription)
|
||||||
|
|
||||||
|
method onStoreToKeychainSuccess*(self: Module, data: string) =
|
||||||
|
if self.keychainActivityReason == KeychainActivityReason.StoreTo:
|
||||||
|
singletonInstance.localAccountSettings.setStoreToKeychainValue(LS_VALUE_STORE)
|
||||||
|
elif self.keychainActivityReason == KeychainActivityReason.RemoveFrom:
|
||||||
|
singletonInstance.localAccountSettings.setStoreToKeychainValue(LS_VALUE_NEVER)
|
||||||
|
self.view.emitStoreToKeychainSuccess()
|
||||||
|
|
||||||
|
method tryStoreToKeyChain*(self: Module) =
|
||||||
|
self.controller.authenticateLoggedInUser()
|
||||||
|
|
||||||
|
method tryRemoveFromKeyChain*(self: Module) =
|
||||||
|
self.keychainActivityReason = KeychainActivityReason.RemoveFrom
|
||||||
|
let myName = singletonInstance.userProfile.getName()
|
||||||
|
self.controller.removeFromKeychain(myName)
|
||||||
|
|
||||||
|
method onUserAuthenticated*(self: Module, pin: string, password: string, keyUid: string) =
|
||||||
|
self.keychainActivityReason = KeychainActivityReason.StoreTo
|
||||||
|
if pin.len > 0:
|
||||||
|
self.controller.storeToKeychain(pin)
|
||||||
|
else:
|
||||||
|
self.controller.storeToKeychain(password)
|
|
@ -63,3 +63,18 @@ QtObject:
|
||||||
|
|
||||||
proc getPasswordStrengthScore*(self: View, password: string): int {.slot.} =
|
proc getPasswordStrengthScore*(self: View, password: string): int {.slot.} =
|
||||||
return self.delegate.getPasswordStrengthScore(password)
|
return self.delegate.getPasswordStrengthScore(password)
|
||||||
|
|
||||||
|
proc storeToKeychainError*(self:View, errorDescription: string) {.signal.}
|
||||||
|
proc emitStoreToKeychainError*(self: View, errorDescription: string) =
|
||||||
|
self.storeToKeychainError(errorDescription)
|
||||||
|
|
||||||
|
proc storeToKeychainSuccess*(self:View) {.signal.}
|
||||||
|
proc emitStoreToKeychainSuccess*(self: View) =
|
||||||
|
self.storeToKeychainSuccess()
|
||||||
|
|
||||||
|
proc tryStoreToKeyChain*(self: View) {.slot.} =
|
||||||
|
self.delegate.tryStoreToKeyChain()
|
||||||
|
|
||||||
|
proc tryRemoveFromKeyChain*(self: View) {.slot.} =
|
||||||
|
self.delegate.tryRemoveFromKeyChain()
|
||||||
|
|
|
@ -1,207 +0,0 @@
|
||||||
import QtQuick 2.13
|
|
||||||
import QtQuick.Controls 2.13
|
|
||||||
import QtQuick.Dialogs 1.3
|
|
||||||
|
|
||||||
import StatusQ.Controls 0.1
|
|
||||||
import StatusQ.Controls.Validators 0.1
|
|
||||||
|
|
||||||
import utils 1.0
|
|
||||||
import shared 1.0
|
|
||||||
import shared.panels 1.0
|
|
||||||
import shared.popups 1.0
|
|
||||||
import shared.controls 1.0
|
|
||||||
|
|
||||||
import "../stores"
|
|
||||||
|
|
||||||
// TODO: replace with StatusModal
|
|
||||||
ModalPopup {
|
|
||||||
property var privacyStore
|
|
||||||
property bool loading: false
|
|
||||||
property bool firstPasswordFieldValid: false
|
|
||||||
property bool repeatPasswordFieldValid: false
|
|
||||||
property string passwordValidationError: ""
|
|
||||||
property string repeatPasswordValidationError: ""
|
|
||||||
|
|
||||||
signal offerToStorePassword(string password, bool runStoreToKeychainPopup)
|
|
||||||
|
|
||||||
id: popup
|
|
||||||
title: qsTr("Store password")
|
|
||||||
height: 500
|
|
||||||
|
|
||||||
onOpened: {
|
|
||||||
if (userProfile.isKeycardUser) {
|
|
||||||
firstPinInputField.statesInitialization()
|
|
||||||
firstPinInputField.forceFocus()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
firstPasswordField.text = "";
|
|
||||||
firstPasswordField.forceActiveFocus(Qt.MouseFocusReason)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.fill: parent
|
|
||||||
leftPadding: d.padding
|
|
||||||
rightPadding: d.padding
|
|
||||||
topPadding: Style.current.xlPadding
|
|
||||||
bottomPadding: Style.current.xlPadding
|
|
||||||
spacing: Style.current.xlPadding
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
id: d
|
|
||||||
|
|
||||||
readonly property int padding: 56
|
|
||||||
readonly property int fontSize: 15
|
|
||||||
}
|
|
||||||
|
|
||||||
Input {
|
|
||||||
id: firstPasswordField
|
|
||||||
width: parent.width - 2 * d.padding
|
|
||||||
visible: !userProfile.isKeycardUser
|
|
||||||
placeholderText: qsTr("Current password...")
|
|
||||||
textField.echoMode: TextInput.Password
|
|
||||||
onTextChanged: {
|
|
||||||
[firstPasswordFieldValid, passwordValidationError] =
|
|
||||||
Utils.validatePasswords("first", firstPasswordField, repeatPasswordField);
|
|
||||||
[repeatPasswordFieldValid, repeatPasswordValidationError] =
|
|
||||||
Utils.validatePasswords("repeat", firstPasswordField, repeatPasswordField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Input {
|
|
||||||
id: repeatPasswordField
|
|
||||||
visible: !userProfile.isKeycardUser
|
|
||||||
width: parent.width - 2 * d.padding
|
|
||||||
enabled: firstPasswordFieldValid
|
|
||||||
placeholderText: qsTr("Confirm password…")
|
|
||||||
textField.echoMode: TextInput.Password
|
|
||||||
Keys.onReturnPressed: function(event) {
|
|
||||||
if (submitBtn.enabled) {
|
|
||||||
submitBtn.clicked(event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onTextChanged: {
|
|
||||||
[repeatPasswordFieldValid, repeatPasswordValidationError] =
|
|
||||||
Utils.validatePasswords("repeat", firstPasswordField, repeatPasswordField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: userProfile.isKeycardUser
|
|
||||||
text: qsTr("Enter new PIN")
|
|
||||||
font.pixelSize: d.fontSize
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusPinInput {
|
|
||||||
id: firstPinInputField
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: userProfile.isKeycardUser
|
|
||||||
validator: StatusIntValidator{bottom: 0; top: 999999;}
|
|
||||||
pinLen: Constants.keycard.general.keycardPinLength
|
|
||||||
|
|
||||||
onPinInputChanged: {
|
|
||||||
if (pinInput.length == Constants.keycard.general.keycardPinLength) {
|
|
||||||
repeatPinInputField.statesInitialization()
|
|
||||||
repeatPinInputField.forceFocus()
|
|
||||||
}
|
|
||||||
|
|
||||||
[firstPasswordFieldValid, passwordValidationError] =
|
|
||||||
Utils.validatePINs("first", firstPinInputField, repeatPinInputField);
|
|
||||||
[repeatPasswordFieldValid, repeatPasswordValidationError] =
|
|
||||||
Utils.validatePINs("repeat", firstPinInputField, repeatPinInputField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: userProfile.isKeycardUser
|
|
||||||
text: qsTr("Repeat PIN")
|
|
||||||
font.pixelSize: d.fontSize
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusPinInput {
|
|
||||||
id: repeatPinInputField
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
visible: userProfile.isKeycardUser
|
|
||||||
validator: StatusIntValidator{bottom: 0; top: 999999;}
|
|
||||||
pinLen: Constants.keycard.general.keycardPinLength
|
|
||||||
|
|
||||||
onPinInputChanged: {
|
|
||||||
[repeatPasswordFieldValid, repeatPasswordValidationError] =
|
|
||||||
Utils.validatePINs("repeat", firstPinInputField, repeatPinInputField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
id: validationError
|
|
||||||
text: {
|
|
||||||
if (passwordValidationError !== "") return passwordValidationError;
|
|
||||||
if (repeatPasswordValidationError !== "") return repeatPasswordValidationError;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
color: Style.current.danger
|
|
||||||
font.pixelSize: 11
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
footer: Item {
|
|
||||||
width: parent.width
|
|
||||||
height: submitBtn.height
|
|
||||||
|
|
||||||
StatusButton {
|
|
||||||
id: submitBtn
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.topMargin: Style.current.padding
|
|
||||||
anchors.right: parent.right
|
|
||||||
state: loading ? "pending" : "default"
|
|
||||||
|
|
||||||
text: userProfile.isKeycardUser? qsTr("Store PIN") : qsTr("Store password")
|
|
||||||
|
|
||||||
enabled: firstPasswordFieldValid && repeatPasswordFieldValid && !loading
|
|
||||||
|
|
||||||
MessageDialog {
|
|
||||||
id: importError
|
|
||||||
title: qsTr("Error importing account")
|
|
||||||
text: qsTr("An error occurred while importing your account: ")
|
|
||||||
icon: StandardIcon.Critical
|
|
||||||
standardButtons: StandardButton.Ok
|
|
||||||
onVisibilityChanged: {
|
|
||||||
loading = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageDialog {
|
|
||||||
id: importLoginError
|
|
||||||
title: qsTr("Login failed")
|
|
||||||
text: qsTr("Login failed. Please re-enter your password and try again.")
|
|
||||||
icon: StandardIcon.Critical
|
|
||||||
standardButtons: StandardButton.Ok
|
|
||||||
onVisibilityChanged: {
|
|
||||||
loading = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (!userProfile.isKeycardUser) {
|
|
||||||
// validate the entered password
|
|
||||||
var validatePassword = privacyStore.validatePassword(repeatPasswordField.text)
|
|
||||||
if(!validatePassword) {
|
|
||||||
firstPasswordFieldValid = false
|
|
||||||
passwordValidationError = qsTr("Incorrect password")
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
popup.offerToStorePassword(repeatPasswordField.text, true)
|
|
||||||
popup.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
popup.offerToStorePassword(repeatPinInputField.pinInput, true)
|
|
||||||
popup.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -29,7 +29,11 @@ QtObject {
|
||||||
return root.privacyModule.validatePassword(password)
|
return root.privacyModule.validatePassword(password)
|
||||||
}
|
}
|
||||||
|
|
||||||
function storeToKeyChain(pass) {
|
function tryStoreToKeyChain() {
|
||||||
mainModule.storePassword(pass);
|
root.privacyModule.tryStoreToKeyChain()
|
||||||
|
}
|
||||||
|
|
||||||
|
function tryRemoveFromKeyChain() {
|
||||||
|
root.privacyModule.tryRemoveFromKeyChain()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ import "../../popups"
|
||||||
import "../../stores"
|
import "../../stores"
|
||||||
import "../../controls"
|
import "../../controls"
|
||||||
import "../../panels"
|
import "../../panels"
|
||||||
import "../../../Onboarding/shared" as OnboardingComponents
|
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
|
@ -69,20 +68,23 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (biometricsSwitch.checked && !biometricsSwitch.currentStoredValue)
|
if (biometricsSwitch.checked && !biometricsSwitch.currentStoredValue)
|
||||||
Global.openPopup(storePasswordModal)
|
root.privacyStore.tryStoreToKeyChain()
|
||||||
else if (!biometricsSwitch.checked)
|
else if (!biometricsSwitch.checked)
|
||||||
localAccountSettings.storeToKeychainValue = Constants.keychain.storedValue.never;
|
root.privacyStore.tryRemoveFromKeyChain()
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
function offerToStorePassword(password, runStoreToKeyChainPopup)
|
Connections {
|
||||||
{
|
target: Qt.platform.os === Constants.mac? root.privacyStore.privacyModule : null
|
||||||
if (Qt.platform.os !== "osx")
|
|
||||||
return;
|
|
||||||
|
|
||||||
localAccountSettings.storeToKeychainValue = Constants.keychain.storedValue.store;
|
function onStoreToKeychainError(errorDescription: string) {
|
||||||
root.privacyStore.storeToKeyChain(password);
|
root.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onStoreToKeychainSuccess() {
|
||||||
|
root.reset()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfileHeader {
|
ProfileHeader {
|
||||||
|
@ -247,15 +249,4 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
|
||||||
id: storePasswordModal
|
|
||||||
|
|
||||||
OnboardingComponents.CreatePasswordModal {
|
|
||||||
privacyStore: root.privacyStore
|
|
||||||
onOfferToStorePassword: {
|
|
||||||
root.offerToStorePassword(password, runStoreToKeychainPopup)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -659,7 +659,7 @@ QtObject {
|
||||||
|
|
||||||
readonly property string windows: "windows"
|
readonly property string windows: "windows"
|
||||||
readonly property string linux: "linux"
|
readonly property string linux: "linux"
|
||||||
readonly property string mac: "mac"
|
readonly property string mac: "osx"
|
||||||
|
|
||||||
// Transaction states
|
// Transaction states
|
||||||
readonly property int addressRequested: 1
|
readonly property int addressRequested: 1
|
||||||
|
|
Loading…
Reference in New Issue