Skip to content

Commit

Permalink
Improved localization for error handling.
Browse files Browse the repository at this point in the history
  • Loading branch information
jensutbult committed Jan 23, 2025
1 parent 6b9c23e commit ad6166d
Show file tree
Hide file tree
Showing 13 changed files with 302 additions and 159 deletions.
8 changes: 4 additions & 4 deletions Authenticator.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
5156D05B265D0538007A94F8 /* TKTokenAlgorithm+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5156D05A265D0538007A94F8 /* TKTokenAlgorithm+Extensions.swift */; };
5156D05D265D2602007A94F8 /* TokenRequestViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5156D05C265D2602007A94F8 /* TokenRequestViewController.swift */; };
5156D05F265D3CEF007A94F8 /* TokenRequestViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5156D05E265D3CEF007A94F8 /* TokenRequestViewModel.swift */; };
5180974326DE185100A122C1 /* ResetOATHViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5180974226DE185100A122C1 /* ResetOATHViewModel.swift */; };
5180974326DE185100A122C1 /* OATHResetViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5180974226DE185100A122C1 /* OATHResetViewModel.swift */; };
51AFD4D62716FCDB008F2630 /* ApplicationSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51AFD4D52716FCDB008F2630 /* ApplicationSettingsViewModel.swift */; };
51AFD4D827196AB6008F2630 /* VersionHistory.plist in Resources */ = {isa = PBXBuildFile; fileRef = 51AFD4D727196AB6008F2630 /* VersionHistory.plist */; };
51AFD4DA271D4278008F2630 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51AFD4D9271D4277008F2630 /* QuartzCore.framework */; };
Expand Down Expand Up @@ -185,7 +185,7 @@
5156D05A265D0538007A94F8 /* TKTokenAlgorithm+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TKTokenAlgorithm+Extensions.swift"; sourceTree = "<group>"; };
5156D05C265D2602007A94F8 /* TokenRequestViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenRequestViewController.swift; sourceTree = "<group>"; };
5156D05E265D3CEF007A94F8 /* TokenRequestViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenRequestViewModel.swift; sourceTree = "<group>"; };
5180974226DE185100A122C1 /* ResetOATHViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResetOATHViewModel.swift; sourceTree = "<group>"; };
5180974226DE185100A122C1 /* OATHResetViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OATHResetViewModel.swift; sourceTree = "<group>"; };
51AFD4D32716FC78008F2630 /* NFCSettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NFCSettingsController.swift; sourceTree = "<group>"; };
51AFD4D52716FCDB008F2630 /* ApplicationSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationSettingsViewModel.swift; sourceTree = "<group>"; };
51AFD4D727196AB6008F2630 /* VersionHistory.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = VersionHistory.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -539,7 +539,7 @@
B4696F402CB6CF2500604F6F /* ConfigurationViewModel.swift */,
B4FE90D12A4431AB00B59170 /* NotificationsViewModel.swift */,
B40D61A12AE7F89500467AE9 /* DisableOTPModel.swift */,
5180974226DE185100A122C1 /* ResetOATHViewModel.swift */,
5180974226DE185100A122C1 /* OATHResetViewModel.swift */,
B44E5EB22C777F22007ABB79 /* OATHPasswordViewModel.swift */,
B4BB02DD2C80BC8500B72904 /* OATHSavedPasswordsViewModel.swift */,
B4BB02E12C81A82300B72904 /* FIDOPINViewModel.swift */,
Expand Down Expand Up @@ -828,7 +828,7 @@
B4C93E65299FC67800C2A8B8 /* View+Extensions.swift in Sources */,
816C685023440D2200209342 /* SecureStoreError.swift in Sources */,
515542602649BDDB00B19C59 /* PasswordStatusViewModel.swift in Sources */,
5180974326DE185100A122C1 /* ResetOATHViewModel.swift in Sources */,
5180974326DE185100A122C1 /* OATHResetViewModel.swift in Sources */,
B4BB02E02C80BEBD00B72904 /* OATHSavedPasswordsView.swift in Sources */,
81FA3C39231AF4F0009C22AB /* UIViewControllerAdditions.swift in Sources */,
816C684623430E0700209342 /* SecureStore.swift in Sources */,
Expand Down
300 changes: 210 additions & 90 deletions Authenticator/Localizable.xcstrings

Large diffs are not rendered by default.

30 changes: 18 additions & 12 deletions Authenticator/Model/FIDOPINViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,17 +112,19 @@ class FIDOPINViewModel: ObservableObject {
}
connection.managementSession { session, error in
guard let session else {
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription)
let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription)
DispatchQueue.main.async {
self.state = .error(error!)
self.state = .error(error)
}
return
}
session.getDeviceInfo { deviceInfo, error in
guard let deviceInfo else {
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription)
let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription)
DispatchQueue.main.async {
self.state = .error(error!)
self.state = .error(error)
}
return
}
Expand All @@ -131,16 +133,18 @@ class FIDOPINViewModel: ObservableObject {
}
connection.fido2Session { session, error in
guard let session else {
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription)
let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription)
DispatchQueue.main.async {
self.state = .error(error!)
self.state = .error(error)
}
return
}
session.getInfoWithCompletion { response, error in
guard let response else {
DispatchQueue.main.async {
self.state = .error(error!)
let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error
self.state = .error(error)
}
return
}
Expand All @@ -162,7 +166,7 @@ class FIDOPINViewModel: ObservableObject {
session.getPinRetries { retries, error in
if let error {
DispatchQueue.main.async {
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription)
YubiKitManager.shared.stopNFCConnection(withErrorMessage: LocalizedErrorWrapper(error: error).localizedDescription)
self.state = .error(error)
}
return
Expand Down Expand Up @@ -200,7 +204,8 @@ class FIDOPINViewModel: ObservableObject {
guard let session else {
DispatchQueue.main.async {
self.isProcessing = false
self.state = .error(error!) // If there is no error and no session crashing is the best thing.
let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error
self.state = .error(error)
}
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription)
return
Expand All @@ -209,7 +214,7 @@ class FIDOPINViewModel: ObservableObject {
DispatchQueue.main.async {
if let error {
self.state = .error(error)
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription)
YubiKitManager.shared.stopNFCConnection(withErrorMessage: LocalizedErrorWrapper(error: error).localizedDescription)
} else {
self.state = .didSet
YubiKitManager.shared.stopNFCConnection(withMessage: String(localized: "PIN has been set"))
Expand All @@ -229,7 +234,8 @@ class FIDOPINViewModel: ObservableObject {
guard let session else {
DispatchQueue.main.async {
self.isProcessing = false
self.state = .error(error!) // If there is no error and no session crashing is the best thing.
let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error
self.state = .error(error)
}
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription)
return
Expand All @@ -238,7 +244,7 @@ class FIDOPINViewModel: ObservableObject {
DispatchQueue.main.async {
if let error {
self.state = .error(error)
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription)
YubiKitManager.shared.stopNFCConnection(withErrorMessage: LocalizedErrorWrapper(error: error).localizedDescription)
} else {
self.state = .didChange
YubiKitManager.shared.stopNFCConnection(withMessage: String(localized: "PIN has been changed"))
Expand Down
13 changes: 8 additions & 5 deletions Authenticator/Model/FIDOResetViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,20 @@ extension FIDOResetViewModel {
func resetNFC(connection: YKFNFCConnection) {
connection.fido2Session { session, error in
guard let session = session else {
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription)
guard let error else { return }
let localizedError = LocalizedErrorWrapper(error: error)
YubiKitManager.shared.stopNFCConnection(withErrorMessage: localizedError.localizedDescription)
DispatchQueue.main.async {
self.state = .error(error!)
self.state = .error(localizedError)
}
return
}
session.reset { error in
DispatchQueue.main.async {
if let error = error {
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription)
self.state = .error(error)
if let error {
let localizedError = LocalizedErrorWrapper(error: error)
YubiKitManager.shared.stopNFCConnection(withErrorMessage: localizedError.localizedDescription)
self.state = .error(localizedError)
} else {
let message = String(localized: "Reset FIDO application", comment: "FIDO reset NFC confirmation message")
YubiKitManager.shared.stopNFCConnection(withMessage: message)
Expand Down
14 changes: 8 additions & 6 deletions Authenticator/Model/OATHPasswordViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,10 @@ class OATHPasswordViewModel: ObservableObject {
connection.startConnection { [weak self] connection in
connection.oathSession { session, error in
guard let session else {
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription)
let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription)
DispatchQueue.main.async {
self?.state = .error(error!)
self?.state = .error(error)
}
return
}
Expand All @@ -108,7 +109,7 @@ class OATHPasswordViewModel: ObservableObject {
if let oathError = error as? YKFOATHError, oathError.code == YKFOATHErrorCode.authenticationRequired.rawValue {
self?.state = .set
} else {
self?.state = .error(error)
self?.state = .error(error) // If we got this far the error is pretty exotic so bailing out like this is ok.
}
}
}
Expand Down Expand Up @@ -138,18 +139,19 @@ class OATHPasswordViewModel: ObservableObject {
connection.startConnection { connection in
connection.oathSession { session, error in
guard let session else {
guard let error else { return }
DispatchQueue.main.async {
self.isProcessing = false
self.state = .error(error!) // If there is no error and no session crashing is the best thing.
self.state = .error(error) // If there is no error and no session crashing is the best thing.
}
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error!.localizedDescription)
YubiKitManager.shared.stopNFCConnection(withErrorMessage: LocalizedErrorWrapper(error: error).localizedDescription)
return
}
session.setPassword(newPassword) { error in
DispatchQueue.main.async {
if let error {
self.state = .error(error)
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription)
YubiKitManager.shared.stopNFCConnection(withErrorMessage: LocalizedErrorWrapper(error: error).localizedDescription)
} else {
self.state = .didSet
YubiKitManager.shared.stopNFCConnection(withMessage: String(localized: "Password has been set"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,25 @@
import Foundation
import OSLog

class ResetOATHViewModel: ObservableObject {
class OATHResetViewModel: ObservableObject {

@Published var state: ResetState = .ready

enum ResetState: Equatable {
case ready, success, error(String)
case ready, success, error(Error)

static func == (lhs: OATHResetViewModel.ResetState, rhs: OATHResetViewModel.ResetState) -> Bool {
switch (lhs, rhs) {
case (.ready, .ready):
return true
case (.success, .success):
return true
case (.error(_), .error(_)):
return true
default:
return false
}
}
}

private let connection = Connection()
Expand All @@ -35,18 +48,18 @@ class ResetOATHViewModel: ObservableObject {
connection.startConnection { connection in
connection.oathSession { session, error in
guard let session = session else {
let errorMessage = error?.localizedDescription ?? String(localized: "Unknown error")
YubiKitManager.shared.stopNFCConnection(withErrorMessage: errorMessage)
let error: LocalizedError = error.map { LocalizedErrorWrapper(error: $0) } ?? UnknownError.error
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription)
DispatchQueue.main.async {
self.state = .error(errorMessage)
self.state = .error(error)
}
return
}
session.reset { error in
DispatchQueue.main.async {
if let error = error {
YubiKitManager.shared.stopNFCConnection(withErrorMessage: error.localizedDescription)
self.state = .error(error.localizedDescription)
YubiKitManager.shared.stopNFCConnection(withErrorMessage: LocalizedErrorWrapper(error: error).localizedDescription)
self.state = .error(error)
} else {
let message = String(localized: "OATH accounts deleted and OATH application reset to factory defaults.", comment: "OATH reset confirmation message")
YubiKitManager.shared.stopNFCConnection(withMessage: message)
Expand Down
Loading

0 comments on commit ad6166d

Please sign in to comment.