Skip to content

Commit

Permalink
Merge branch 'main' into feat/email-mfa
Browse files Browse the repository at this point in the history
  • Loading branch information
harsh62 authored Sep 26, 2024
2 parents 7aaee26 + 1ec95fb commit 9e3c844
Show file tree
Hide file tree
Showing 20 changed files with 62 additions and 23 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## 1.1.8 (2024-09-20)

### Bug Fixes
- **Authenticator**: Adding new error localizations for limits exceeded (#96)

## 1.1.7 (2024-09-13)

### Bug Fixes
- **Authenticator**: Allowing to only override the desired errors when invoking the errorMap functions (#93)

## 1.1.6 (2024-08-13)

### Bug Fixes
Expand Down
2 changes: 1 addition & 1 deletion Sources/Authenticator/Authenticator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ public struct Authenticator<LoadingContent: View,

/// Sets a custom error mapping function for the `AuthError`s that are displayed
/// - Parameter errorTransform: A closure that takes an `AuthError` and returns a ``AuthenticatorError`` that will be displayed.
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError) -> Self {
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError?) -> Self {
for contentState in contentStates.allObjects {
contentState.errorTransform = errorTransform
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Authenticator/Constants/ComponentInformation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
import Foundation

public class ComponentInformation {
public static let version = "1.1.6"
public static let version = "1.1.8"
public static let name = "amplify-ui-swift-authenticator"
}
2 changes: 2 additions & 0 deletions Sources/Authenticator/Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@

/* Authenticator Errors */
"authenticator.authError.incorrectCredentials" = "Incorrect username or password";
"authenticator.authError.passwordAttemptsExceeded" = "You've reached the password attempts limit. Please try again later";
"authenticator.authError.continueSignInWithMFASelection.noSelectionError" = "Please select an MFA method to continue";
"authenticator.unknownError" = "Sorry, something went wrong";

Expand All @@ -192,6 +193,7 @@
"authenticator.cognitoError.network" = "Please check your connectivity";
"authenticator.cognitoError.usernameExists" = "Username already exists";
"authenticator.cognitoError.userNotFound" = "User not found";
"authenticator.cognitoError.limitExceeded" = "You've reached the request limit. Please try again later";

/* Toolbar displayed on top of the keyboard */
"authenticator.keyboardToolbar.Done" = "Done";
15 changes: 10 additions & 5 deletions Sources/Authenticator/States/AuthenticatorBaseState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class AuthenticatorBaseState: ObservableObject {

@ObservedObject var credentials: Credentials

var errorTransform: ((AuthError) -> AuthenticatorError)? = nil
var errorTransform: ((AuthError) -> AuthenticatorError?)? = nil
private(set) var authenticatorState: AuthenticatorStateProtocol = .empty

init(credentials: Credentials) {
Expand Down Expand Up @@ -188,8 +188,8 @@ public class AuthenticatorBaseState: ObservableObject {
return .unknown(from: error)
}

if let errorTransform = errorTransform {
return errorTransform(authError)
if let customError = errorTransform?(authError) {
return customError
}

if let localizedMessage = localizedMessage(for: authError) {
Expand All @@ -202,8 +202,13 @@ public class AuthenticatorBaseState: ObservableObject {
}

private func localizedMessage(for error: AuthError) -> String? {
if case .notAuthorized(_, _, _) = error {
return "authenticator.authError.incorrectCredentials".localized()
if case .notAuthorized(let description, _, _) = error {
switch description {
case "Password attempts exceeded":
return "authenticator.authError.passwordAttemptsExceeded".localized()
default:
return "authenticator.authError.incorrectCredentials".localized()
}
}

if case .validation(let field, _, _, _) = error {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Authenticator/Views/ConfirmResetPasswordView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ public struct ConfirmResetPasswordView<Header: View,

/// Sets a custom error mapping function for the `AuthError`s that are displayed
/// - Parameter errorTransform: A closure that takes an `AuthError` and returns a ``AuthenticatorError`` that will be displayed.
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError) -> Self {
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError?) -> Self {
state.errorTransform = errorTransform
return self
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public struct ConfirmSignInWithCustomChallengeView<Header: View,

/// Sets a custom error mapping function for the `AuthError`s that are displayed
/// - Parameter errorTransform: A closure that takes an `AuthError` and returns a ``AuthenticatorError`` that will be displayed.
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError) -> Self {
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError?) -> Self {
state.errorTransform = errorTransform
return self
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public struct ConfirmSignInWithMFACodeView<Header: View,

/// Sets a custom error mapping function for the `AuthError`s that are displayed
/// - Parameter errorTransform: A closure that takes an `AuthError` and returns a ``AuthenticatorError`` that will be displayed.
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError) -> Self {
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError?) -> Self {
state.errorTransform = errorTransform
return self
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public struct ConfirmSignInWithNewPasswordView<Header: View,

/// Sets a custom error mapping function for the `AuthError`s that are displayed
/// - Parameter errorTransform: A closure that takes an `AuthError` and returns a ``AuthenticatorError`` that will be displayed.
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError) -> Self {
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError?) -> Self {
state.errorTransform = errorTransform
return self
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public struct ConfirmSignInWithTOTPView<Header: View,

/// Sets a custom error mapping function for the `AuthError`s that are displayed
/// - Parameter errorTransform: A closure that takes an `AuthError` and returns a ``AuthenticatorError`` that will be displayed.
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError) -> Self {
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError?) -> Self {
state.errorTransform = errorTransform
return self
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Authenticator/Views/ConfirmSignUpView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public struct ConfirmSignUpView<Header: View,

/// Sets a custom error mapping function for the `AuthError`s that are displayed
/// - Parameter errorTransform: A closure that takes an `AuthError` and returns a ``AuthenticatorError`` that will be displayed.
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError) -> Self {
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError?) -> Self {
state.errorTransform = errorTransform
return self
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Authenticator/Views/ConfirmVerifyUserView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public struct ConfirmVerifyUserView<Header: View,

/// Sets a custom error mapping function for the `AuthError`s that are displayed
/// - Parameter errorTransform: A closure that takes an `AuthError` and returns a ``AuthenticatorError`` that will be displayed.
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError) -> Self {
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError?) -> Self {
state.errorTransform = errorTransform
return self
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public struct ContinueSignInWithMFASelectionView<Header: View,

/// Sets a custom error mapping function for the `AuthError`s that are displayed
/// - Parameter errorTransform: A closure that takes an `AuthError` and returns a ``AuthenticatorError`` that will be displayed.
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError) -> Self {
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError?) -> Self {
state.errorTransform = errorTransform
return self
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public struct ContinueSignInWithTOTPSetupView<Header: View,

/// Sets a custom error mapping function for the `AuthError`s that are displayed
/// - Parameter errorTransform: A closure that takes an `AuthError` and returns a ``AuthenticatorError`` that will be displayed.
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError) -> Self {
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError?) -> Self {
state.errorTransform = errorTransform
return self
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct ConfirmSignInWithCodeView<Header: View,
@ViewBuilder footerContent: () -> Footer = {
EmptyView()
},
errorTransform: ((AuthError) -> AuthenticatorError)? = nil
errorTransform: ((AuthError) -> AuthenticatorError?)? = nil,
) {
self.state = state
self.headerContent = headerContent()
Expand Down
2 changes: 1 addition & 1 deletion Sources/Authenticator/Views/ResetPasswordView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public struct ResetPasswordView<Header: View,

/// Sets a custom error mapping function for the `AuthError`s that are displayed
/// - Parameter errorTransform: A closure that takes an `AuthError` and returns a ``AuthenticatorError`` that will be displayed.
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError) -> Self {
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError?) -> Self {
state.errorTransform = errorTransform
return self
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Authenticator/Views/SignInView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public struct SignInView<Header: View,

/// Sets a custom error mapping function for the `AuthError`s that are displayed
/// - Parameter errorTransform: A closure that takes an `AuthError` and returns a ``AuthenticatorError`` that will be displayed.
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError) -> Self {
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError?) -> Self {
state.errorTransform = errorTransform
return self
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Authenticator/Views/SignUpView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public struct SignUpView<Header: View,

/// Sets a custom error mapping function for the `AuthError`s that are displayed
/// - Parameter errorTransform: A closure that takes an `AuthError` and returns a ``AuthenticatorError`` that will be displayed.
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError) -> Self {
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError?) -> Self {
state.errorTransform = errorTransform
return self
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Authenticator/Views/VerifyUserView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public struct VerifyUserView<Header: View,

/// Sets a custom error mapping function for the `AuthError`s that are displayed
/// - Parameter errorTransform: A closure that takes an `AuthError` and returns a ``AuthenticatorError`` that will be displayed.
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError) -> Self {
public func errorMap(_ errorTransform: @escaping (AuthError) -> AuthenticatorError?) -> Self {
state.errorTransform = errorTransform
return self
}
Expand Down
26 changes: 24 additions & 2 deletions Tests/AuthenticatorTests/States/AuthenticatorBaseStateTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,14 @@ class AuthenticatorBaseStateTests: XCTestCase {
XCTAssertEqual(authenticatorError.content, "authenticator.unknownError".localized())
}

func testError_withNotAuthorizedError_shouldReturnLocalizedError() {
let authenticatorError = state.error(for: AuthError.notAuthorized("description", "recovery", nil))
func testError_withNotAuthorizedError_withPasswordAttemptsExceededDescription_shouldReturnLocalizedError() {
let authenticatorError = state.error(for: AuthError.notAuthorized("Password attempts exceeded", "recovery", nil))
XCTAssertEqual(authenticatorError.style, .error)
XCTAssertEqual(authenticatorError.content, "authenticator.authError.passwordAttemptsExceeded".localized())
}

func testError_withNotAuthorizedError_withAnotherDescription_shouldReturnLocalizedError() {
let authenticatorError = state.error(for: AuthError.notAuthorized("Unable to sign in", "recovery", nil))
XCTAssertEqual(authenticatorError.style, .error)
XCTAssertEqual(authenticatorError.content, "authenticator.authError.incorrectCredentials".localized())
}
Expand All @@ -239,6 +245,22 @@ class AuthenticatorBaseStateTests: XCTestCase {
XCTAssertEqual(authenticatorError.content, "A custom error")
}

func testError_withCustomErrorTransformThatReturnsNil_shouldReturnDefaultError() {
var closureCount = 0
state.errorTransform = { error in
closureCount = 1
if case .service = error {
return .error(message: "A service error")
}
return nil
}
let authenticatorError = state.error(for: AuthError.notAuthorized("description", "recovery", nil))
XCTAssertEqual(closureCount, 1)
XCTAssertEqual(authenticatorError.style, .error)
let expectedMessage = "authenticator.authError.incorrectCredentials".localized()
XCTAssertEqual(authenticatorError.content, expectedMessage)
}

func testError_withLocalizedCognitoError_shouldReturnLocalizedError() {
let cognitoError = AWSCognitoAuthError.userNotFound
let authenticatorError = state.error(for: AuthError.service("description", "recovery", cognitoError))
Expand Down

0 comments on commit 9e3c844

Please sign in to comment.