element-ios/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseVie...

153 lines
5.2 KiB
Swift

/*
Copyright 2019-2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/
import Foundation
final class KeyBackupSetupPassphraseViewModel: KeyBackupSetupPassphraseViewModelType {
// MARK: - Properties
// MARK: Private
private(set) var passphraseStrength: PasswordStrength = .tooGuessable
private let passwordStrengthManager: PasswordStrengthManager
private let keyBackup: MXKeyBackup
private let coordinatorDelegateQueue: OperationQueue
private var createKeyBackupOperation: MXHTTPOperation?
// MARK: Public
var passphrase: String? {
didSet {
self.updatePassphraseStrength()
}
}
var confirmPassphrase: String?
var isPassphraseValid: Bool {
return self.passphraseStrength == .veryUnguessable
}
var isConfirmPassphraseValid: Bool {
guard self.isPassphraseValid, let confirmPassphrase = self.confirmPassphrase else {
return false
}
return confirmPassphrase == passphrase
}
var isFormValid: Bool {
return self.isPassphraseValid && self.isConfirmPassphraseValid
}
weak var viewDelegate: KeyBackupSetupPassphraseViewModelViewDelegate?
weak var coordinatorDelegate: KeyBackupSetupPassphraseViewModelCoordinatorDelegate?
// MARK: - Setup
init(keyBackup: MXKeyBackup) {
self.passwordStrengthManager = PasswordStrengthManager()
self.keyBackup = keyBackup
self.coordinatorDelegateQueue = OperationQueue.vc_createSerialOperationQueue(name: "\(type(of: self)).coordinatorDelegateQueue")
}
deinit {
self.createKeyBackupOperation?.cancel()
}
// MARK: - Public
func process(viewAction: KeyBackupSetupPassphraseViewAction) {
switch viewAction {
case .setupPassphrase:
self.setupPassphrase()
case .setupRecoveryKey:
self.setupRecoveryKey()
case .skip:
self.coordinatorDelegateQueue.vc_pause()
self.viewDelegate?.keyBackupSetupPassphraseViewModelShowSkipAlert(self)
case.skipAlertContinue:
self.coordinatorDelegateQueue.vc_resume()
case.skipAlertSkip:
self.coordinatorDelegateQueue.cancelAllOperations()
self.coordinatorDelegate?.keyBackupSetupPassphraseViewModelDidCancel(self)
}
}
// MARK: - Private
private func setupPassphrase() {
guard let passphrase = self.passphrase else {
return
}
self.update(viewState: .loading)
self.keyBackup.prepareKeyBackupVersion(withPassword: passphrase, algorithm: nil, success: { [weak self] (megolmBackupCreationInfo) in
guard let sself = self else {
return
}
sself.createKeyBackupOperation = sself.keyBackup.createKeyBackupVersion(megolmBackupCreationInfo, success: { (_) in
sself.update(viewState: .loaded)
sself.coordinatorDelegateQueue.addOperation {
DispatchQueue.main.async {
sself.coordinatorDelegate?.keyBackupSetupPassphraseViewModel(sself, didCreateBackupFromPassphraseWithResultingRecoveryKey: megolmBackupCreationInfo.recoveryKey)
}
}
}, failure: { (error) in
self?.update(viewState: .error(error))
})
}, failure: { [weak self] error in
self?.update(viewState: .error(error))
})
}
private func setupRecoveryKey() {
self.update(viewState: .loading)
self.keyBackup.prepareKeyBackupVersion(withPassword: nil, algorithm: nil, success: { [weak self] (megolmBackupCreationInfo) in
guard let sself = self else {
return
}
sself.createKeyBackupOperation = sself.keyBackup.createKeyBackupVersion(megolmBackupCreationInfo, success: { (_) in
sself.update(viewState: .loaded)
sself.coordinatorDelegateQueue.addOperation {
DispatchQueue.main.async {
sself.coordinatorDelegate?.keyBackupSetupPassphraseViewModel(sself, didCreateBackupFromRecoveryKey: megolmBackupCreationInfo.recoveryKey)
}
}
}, failure: { (error) in
self?.update(viewState: .error(error))
})
}, failure: { [weak self] error in
self?.update(viewState: .error(error))
})
}
private func updatePassphraseStrength() {
self.passphraseStrength = self.passwordStrength(for: self.passphrase)
}
private func passwordStrength(for password: String?) -> PasswordStrength {
guard let password = password else {
return .tooGuessable
}
return self.passwordStrengthManager.passwordStrength(for: password)
}
private func update(viewState: KeyBackupSetupPassphraseViewState) {
self.viewDelegate?.keyBackupSetupPassphraseViewModel(self, didUpdateViewState: viewState)
}
}