From a76284a55880354a9c5a1b1f289fecf62155cb62 Mon Sep 17 00:00:00 2001 From: Ian Saultz <52051793+atierian@users.noreply.github.com> Date: Tue, 10 Oct 2023 09:59:02 -0400 Subject: [PATCH] fix: add AuthErrorConvertible conformance to CommonRuntimeError (#3287) --- ...monRunTimeError+AuthErrorConvertible.swift | 42 +++++++++++++++++++ ...uthenticationProviderDeleteUserTests.swift | 4 -- .../AuthDeleteUserTests.swift | 1 - .../ClientRuntimeFoundationBridge.swift | 2 - 4 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Service/ErrorMapping/CommonRunTimeError+AuthErrorConvertible.swift diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Service/ErrorMapping/CommonRunTimeError+AuthErrorConvertible.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Service/ErrorMapping/CommonRunTimeError+AuthErrorConvertible.swift new file mode 100644 index 0000000000..8244b277a5 --- /dev/null +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Service/ErrorMapping/CommonRunTimeError+AuthErrorConvertible.swift @@ -0,0 +1,42 @@ +// +// Copyright Amazon.com Inc. or its affiliates. +// All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + +import Foundation +import Amplify +import AwsCommonRuntimeKit +import AwsCIo +import AwsCHttp + +private let connectivityErrorCodes: Set = [ + AWS_ERROR_HTTP_CONNECTION_CLOSED.rawValue, + AWS_ERROR_HTTP_SERVER_CLOSED.rawValue, + AWS_IO_DNS_INVALID_NAME.rawValue, + AWS_IO_DNS_NO_ADDRESS_FOR_HOST.rawValue, + AWS_IO_DNS_QUERY_FAILED.rawValue, + AWS_IO_SOCKET_CONNECT_ABORTED.rawValue, + AWS_IO_SOCKET_CONNECTION_REFUSED.rawValue, + AWS_IO_SOCKET_CLOSED.rawValue, + AWS_IO_SOCKET_NETWORK_DOWN.rawValue, + AWS_IO_SOCKET_NO_ROUTE_TO_HOST.rawValue, + AWS_IO_SOCKET_NOT_CONNECTED.rawValue, + AWS_IO_SOCKET_TIMEOUT.rawValue, + AWS_IO_TLS_NEGOTIATION_TIMEOUT.rawValue, + UInt32(AWS_HTTP_STATUS_CODE_408_REQUEST_TIMEOUT.rawValue) +] + +extension CommonRunTimeError: AuthErrorConvertible { + var authError: AuthError { + let error: CRTError + switch self { case .crtError(let crtError): error = crtError } + + if connectivityErrorCodes.contains(UInt32(error.code)) { + return .service(error.name, error.message, AWSCognitoAuthError.network) + } else { + return .unknown("\(error.name) - \(error.message)", self) + } + } +} diff --git a/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/TaskTests/ClientBehaviorTests/AuthenticationProviderDeleteUserTests.swift b/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/TaskTests/ClientBehaviorTests/AuthenticationProviderDeleteUserTests.swift index c24e5357ba..d665ea8881 100644 --- a/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/TaskTests/ClientBehaviorTests/AuthenticationProviderDeleteUserTests.swift +++ b/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/TaskTests/ClientBehaviorTests/AuthenticationProviderDeleteUserTests.swift @@ -77,8 +77,6 @@ class AuthenticationProviderDeleteUserTests: BasePluginTest { /// - I should get a .service error with .network as underlying error /// func testOfflineDeleteUser() async throws { - // TODO: How are client side retry errors now modeled? - throw XCTSkip() mockIdentityProvider = MockIdentityProvider( mockRevokeTokenResponse: { _ in try await RevokeTokenOutputResponse(httpResponse: .init(body: .empty, statusCode: .ok)) @@ -113,8 +111,6 @@ class AuthenticationProviderDeleteUserTests: BasePluginTest { /// - I should get a valid response for the second call /// func testOfflineDeleteUserAndRetry() async throws { - // TODO: How are client side retry errors now modeled? - throw XCTSkip() mockIdentityProvider = MockIdentityProvider( mockRevokeTokenResponse: { _ in try await RevokeTokenOutputResponse(httpResponse: .init(body: .empty, statusCode: .ok)) diff --git a/AmplifyPlugins/Auth/Tests/AuthHostApp/AuthIntegrationTests/AuthDeleteUserTests/AuthDeleteUserTests.swift b/AmplifyPlugins/Auth/Tests/AuthHostApp/AuthIntegrationTests/AuthDeleteUserTests/AuthDeleteUserTests.swift index 5304a5b5e1..a7d09a8796 100644 --- a/AmplifyPlugins/Auth/Tests/AuthHostApp/AuthIntegrationTests/AuthDeleteUserTests/AuthDeleteUserTests.swift +++ b/AmplifyPlugins/Auth/Tests/AuthHostApp/AuthIntegrationTests/AuthDeleteUserTests/AuthDeleteUserTests.swift @@ -59,7 +59,6 @@ class AuthDeleteUserTests: AWSAuthBaseTest { Should produce .service error with underlyingError of .userNotFound || .limitExceed Received: \(error) """) - } } catch { XCTFail("Expected AuthError - received: \(error)") diff --git a/AmplifyPlugins/Core/AWSPluginsCore/Utils/CustomHttpClientEngine/ClientRuntimeFoundationBridge.swift b/AmplifyPlugins/Core/AWSPluginsCore/Utils/CustomHttpClientEngine/ClientRuntimeFoundationBridge.swift index 763e43ac31..306165b134 100644 --- a/AmplifyPlugins/Core/AWSPluginsCore/Utils/CustomHttpClientEngine/ClientRuntimeFoundationBridge.swift +++ b/AmplifyPlugins/Core/AWSPluginsCore/Utils/CustomHttpClientEngine/ClientRuntimeFoundationBridge.swift @@ -45,8 +45,6 @@ extension ClientRuntime.HttpResponse { convenience init(httpURLResponse: HTTPURLResponse, data: Data) throws { let headers = Self.headers(from: httpURLResponse.allHeaderFields) - // TODO: double check if this works as expected - // Previously this needed to be `HttpBody.stream()` let body = HttpBody.data(data) guard let statusCode = HttpStatusCode(rawValue: httpURLResponse.statusCode) else {