mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-24 18:42:47 +02:00
Logout automatically when pin/biometrics provided wrong too many times
This commit is contained in:
@@ -41,6 +41,7 @@ final class EnterPinCodeViewModel: EnterPinCodeViewModelType {
|
||||
weak var viewDelegate: EnterPinCodeViewModelViewDelegate?
|
||||
weak var coordinatorDelegate: EnterPinCodeViewModelCoordinatorDelegate?
|
||||
private let pinCodePreferences: PinCodePreferences
|
||||
private let localAuthenticationService: LocalAuthenticationService
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
@@ -49,6 +50,7 @@ final class EnterPinCodeViewModel: EnterPinCodeViewModelType {
|
||||
self.originalViewMode = viewMode
|
||||
self.viewMode = viewMode
|
||||
self.pinCodePreferences = pinCodePreferences
|
||||
self.localAuthenticationService = LocalAuthenticationService(pinCodePreferences: pinCodePreferences)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
@@ -141,6 +143,12 @@ final class EnterPinCodeViewModel: EnterPinCodeViewModelType {
|
||||
if currentPin != pinCodePreferences.pin {
|
||||
// no match
|
||||
numberOfFailuresDuringEnterPIN += 1
|
||||
pinCodePreferences.numberOfPinFailures += 1
|
||||
if viewMode == .unlock && localAuthenticationService.shouldLogOutUser() {
|
||||
// log out user
|
||||
self.coordinatorDelegate?.enterPinCodeViewModelDidCompleteWithReset(self)
|
||||
return
|
||||
}
|
||||
if numberOfFailuresDuringEnterPIN < pinCodePreferences.allowedNumberOfTrialsBeforeAlert {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
self.viewDelegate?.enterPinCodeViewModel(self, didUpdateViewState: .wrongPin)
|
||||
@@ -153,6 +161,9 @@ final class EnterPinCodeViewModel: EnterPinCodeViewModelType {
|
||||
}
|
||||
} else {
|
||||
// match
|
||||
// we can use biometrics anymore, if set
|
||||
pinCodePreferences.canUseBiometricsToUnlock = nil
|
||||
pinCodePreferences.resetCounters()
|
||||
// complete with a little delay
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
self.coordinatorDelegate?.enterPinCodeViewModelDidComplete(self)
|
||||
|
||||
@@ -176,7 +176,7 @@ final class PinCodePreferences: NSObject {
|
||||
}
|
||||
|
||||
var isBiometricsSet: Bool {
|
||||
return biometricsEnabled == true
|
||||
return biometricsEnabled == true && canUseBiometricsToUnlock == true
|
||||
}
|
||||
|
||||
func localizedBiometricsName() -> String? {
|
||||
|
||||
@@ -53,8 +53,7 @@ final class SetPinCoordinator: SetPinCoordinatorType {
|
||||
private func getRootCoordinator() -> Coordinator & Presentable {
|
||||
switch viewMode {
|
||||
case .unlock:
|
||||
let canUseBiometricsToUnlock = pinCodePreferences.canUseBiometricsToUnlock ?? true
|
||||
if pinCodePreferences.isBiometricsSet && canUseBiometricsToUnlock {
|
||||
if pinCodePreferences.isBiometricsSet {
|
||||
return createSetupBiometricsCoordinator()
|
||||
} else {
|
||||
return createEnterPinCodeCoordinator()
|
||||
@@ -139,6 +138,7 @@ extension SetPinCoordinator: EnterPinCodeCoordinatorDelegate {
|
||||
|
||||
func enterPinCodeCoordinatorDidCompleteWithReset(_ coordinator: EnterPinCodeCoordinatorType) {
|
||||
self.delegate?.setPinCoordinatorDidCompleteWithReset(self)
|
||||
pinCodePreferences.reset()
|
||||
}
|
||||
|
||||
func enterPinCodeCoordinator(_ coordinator: EnterPinCodeCoordinatorType, didCompleteWithPin pin: String) {
|
||||
@@ -171,7 +171,13 @@ extension SetPinCoordinator: SetupBiometricsCoordinatorDelegate {
|
||||
}
|
||||
|
||||
func setupBiometricsCoordinatorDidCompleteWithReset(_ coordinator: SetupBiometricsCoordinatorType) {
|
||||
self.delegate?.setPinCoordinatorDidCompleteWithReset(self)
|
||||
if viewMode == .unlock && pinCodePreferences.isPinSet {
|
||||
// and user also has set a pin, so fallback to it
|
||||
setRootCoordinator(createEnterPinCodeCoordinator())
|
||||
} else {
|
||||
// cascade rest
|
||||
self.delegate?.setPinCoordinatorDidCompleteWithReset(self)
|
||||
}
|
||||
}
|
||||
|
||||
func setupBiometricsCoordinatorDidCancel(_ coordinator: SetupBiometricsCoordinatorType) {
|
||||
|
||||
@@ -28,6 +28,7 @@ final class SetupBiometricsViewModel: SetupBiometricsViewModelType {
|
||||
private let session: MXSession?
|
||||
private let viewMode: SetPinCoordinatorViewMode
|
||||
private let pinCodePreferences: PinCodePreferences
|
||||
private let localAuthenticationService: LocalAuthenticationService
|
||||
|
||||
// MARK: Public
|
||||
|
||||
@@ -40,6 +41,7 @@ final class SetupBiometricsViewModel: SetupBiometricsViewModelType {
|
||||
self.session = session
|
||||
self.viewMode = viewMode
|
||||
self.pinCodePreferences = pinCodePreferences
|
||||
self.localAuthenticationService = LocalAuthenticationService(pinCodePreferences: pinCodePreferences)
|
||||
}
|
||||
|
||||
deinit {
|
||||
@@ -74,26 +76,47 @@ final class SetupBiometricsViewModel: SetupBiometricsViewModelType {
|
||||
// MARK: - Private
|
||||
|
||||
private func enableDisableBiometrics() {
|
||||
LocalAuthenticationService.isShowingBiometrics = true
|
||||
LAContext().evaluatePolicy(.deviceOwnerAuthentication, localizedReason: VectorL10n.biometricsUsageReason) { (success, error) in
|
||||
if success {
|
||||
// complete after a little delay
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
self.pinCodePreferences.canUseBiometricsToUnlock = nil
|
||||
self.pinCodePreferences.resetCounters()
|
||||
self.coordinatorDelegate?.setupBiometricsViewModelDidComplete(self)
|
||||
LocalAuthenticationService.isShowingBiometrics = false
|
||||
}
|
||||
} else {
|
||||
LocalAuthenticationService.isShowingBiometrics = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func unlockWithBiometrics() {
|
||||
LocalAuthenticationService.isShowingBiometrics = true
|
||||
LAContext().evaluatePolicy(.deviceOwnerAuthentication, localizedReason: VectorL10n.biometricsUsageReason) { (success, error) in
|
||||
if success {
|
||||
// complete after a little delay
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
self.pinCodePreferences.canUseBiometricsToUnlock = nil
|
||||
self.pinCodePreferences.resetCounters()
|
||||
self.coordinatorDelegate?.setupBiometricsViewModelDidComplete(self)
|
||||
LocalAuthenticationService.isShowingBiometrics = false
|
||||
}
|
||||
} else {
|
||||
if let error = error as NSError?, error.code == LAError.Code.userCancel.rawValue || error.code == LAError.Code.userFallback.rawValue {
|
||||
self.userCancelledUnlockWithBiometrics()
|
||||
if let error = error as NSError? {
|
||||
self.pinCodePreferences.numberOfBiometricsFailures += 1
|
||||
if self.localAuthenticationService.shouldLogOutUser() {
|
||||
// biometrics can't be used until further unlock with pin or a new log in
|
||||
self.pinCodePreferences.canUseBiometricsToUnlock = false
|
||||
DispatchQueue.main.async {
|
||||
self.coordinatorDelegate?.setupBiometricsViewModelDidCompleteWithReset(self)
|
||||
LocalAuthenticationService.isShowingBiometrics = false
|
||||
}
|
||||
} else if error.code == LAError.Code.userCancel.rawValue || error.code == LAError.Code.userFallback.rawValue {
|
||||
self.userCancelledUnlockWithBiometrics()
|
||||
LocalAuthenticationService.isShowingBiometrics = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,6 +124,7 @@ final class SetupBiometricsViewModel: SetupBiometricsViewModelType {
|
||||
|
||||
private func userCancelledUnlockWithBiometrics() {
|
||||
if pinCodePreferences.isPinSet {
|
||||
self.pinCodePreferences.canUseBiometricsToUnlock = false
|
||||
// cascade this cancellation, coordinator should take care of it
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
self.coordinatorDelegate?.setupBiometricsViewModelDidCancel(self)
|
||||
|
||||
Reference in New Issue
Block a user