Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Auth] Use result type to wrap completion handlers internally #13563

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions FirebaseAuth/Sources/Swift/Auth/Auth.swift
Original file line number Diff line number Diff line change
Expand Up @@ -295,9 +295,9 @@ extension Auth: AuthInterop {
Task {
do {
let response = try await AuthBackend.call(with: request)
Auth.wrapMainAsync(callback: completion, withParam: response.signinMethods, error: nil)
Auth.wrapMainAsync(callback: completion, with: .success(response.signinMethods))
} catch {
Auth.wrapMainAsync(callback: completion, withParam: nil, error: error)
Auth.wrapMainAsync(callback: completion, with: .failure(error))
}
}
}
Expand Down Expand Up @@ -1004,9 +1004,9 @@ extension Auth: AuthInterop {
let actionCodeInfo = ActionCodeInfo(withOperation: operation,
email: email,
newEmail: response.verifiedEmail)
Auth.wrapMainAsync(callback: completion, withParam: actionCodeInfo, error: nil)
Auth.wrapMainAsync(callback: completion, with: .success(actionCodeInfo))
} catch {
Auth.wrapMainAsync(callback: completion, withParam: nil, error: error)
Auth.wrapMainAsync(callback: completion, with: .failure(error))
}
}
}
Expand Down Expand Up @@ -2224,7 +2224,11 @@ extension Auth: AuthInterop {
((AuthDataResult?, Error?) -> Void)?) -> (AuthDataResult?, Error?) -> Void {
let authDataCallback: (((AuthDataResult?, Error?) -> Void)?, AuthDataResult?, Error?) -> Void =
{ callback, result, error in
Auth.wrapMainAsync(callback: callback, withParam: result, error: error)
if let result {
Auth.wrapMainAsync(callback: callback, with: .success(result))
} else if let error {
Auth.wrapMainAsync(callback: callback, with: .failure(error))
}
}
return { authResult, error in
if let error {
Expand Down Expand Up @@ -2261,11 +2265,14 @@ extension Auth: AuthInterop {
}

class func wrapMainAsync<T: Any>(callback: ((T?, Error?) -> Void)?,
withParam param: T?,
error: Error?) -> Void {
if let callback {
DispatchQueue.main.async {
callback(param, error)
with result: Result<T, Error>) -> Void {
guard let callback else { return }
DispatchQueue.main.async {
switch result {
case let .success(success):
callback(success, nil)
case let .failure(error):
callback(nil, error)
}
}
}
Expand Down
22 changes: 14 additions & 8 deletions FirebaseAuth/Sources/Swift/AuthProvider/PhoneAuthProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ import Foundation
uiDelegate: uiDelegate,
multiFactorSession: multiFactorSession
)
Auth.wrapMainAsync(callback: completion, withParam: verificationID, error: nil)
Auth.wrapMainAsync(callback: completion, with: .success(verificationID))
} catch {
Auth.wrapMainAsync(callback: completion, withParam: nil, error: error)
Auth.wrapMainAsync(callback: completion, with: .failure(error))
}
}
}
Expand Down Expand Up @@ -184,7 +184,7 @@ import Foundation
private func internalVerify(phoneNumber: String,
uiDelegate: AuthUIDelegate?,
multiFactorSession: MultiFactorSession? = nil) async throws
-> String? {
-> String {
guard phoneNumber.count > 0 else {
throw AuthErrorUtils.missingPhoneNumberError(message: nil)
}
Expand All @@ -209,7 +209,7 @@ import Foundation
private func verifyClAndSendVerificationCode(toPhoneNumber phoneNumber: String,
retryOnInvalidAppCredential: Bool,
uiDelegate: AuthUIDelegate?) async throws
-> String? {
-> String {
let codeIdentity = try await verifyClient(withUIDelegate: uiDelegate)
let request = SendVerificationCodeRequest(phoneNumber: phoneNumber,
codeIdentity: codeIdentity,
Expand All @@ -236,7 +236,7 @@ import Foundation
retryOnInvalidAppCredential: Bool,
multiFactorSession session: MultiFactorSession?,
uiDelegate: AuthUIDelegate?) async throws
-> String? {
-> String {
if let settings = auth.settings,
settings.isAppVerificationDisabledForTesting {
let request = SendVerificationCodeRequest(
Expand Down Expand Up @@ -264,15 +264,21 @@ import Foundation
enrollmentInfo: startMFARequestInfo,
requestConfiguration: auth.requestConfiguration)
let response = try await AuthBackend.call(with: request)
return response.phoneSessionInfo?.sessionInfo
guard let sessionInfo = response.phoneSessionInfo?.sessionInfo else {
throw AuthErrorUtils.error(code: .missingMultiFactorInfo)
}
return sessionInfo
} else {
let request = StartMFASignInRequest(MFAPendingCredential: session.mfaPendingCredential,
MFAEnrollmentID: session.multiFactorInfo?.uid,
signInInfo: startMFARequestInfo,
requestConfiguration: auth.requestConfiguration)

let response = try await AuthBackend.call(with: request)
return response.responseInfo?.sessionInfo
guard let sessionInfo = response.responseInfo?.sessionInfo else {
throw AuthErrorUtils.error(code: .multiFactorInfoNotFound)
}
return sessionInfo
}
} catch {
return try await handleVerifyErrorWithRetry(
Expand All @@ -289,7 +295,7 @@ import Foundation
phoneNumber: String,
retryOnInvalidAppCredential: Bool,
multiFactorSession session: MultiFactorSession?,
uiDelegate: AuthUIDelegate?) async throws -> String? {
uiDelegate: AuthUIDelegate?) async throws -> String {
if (error as NSError).code == AuthErrorCode.invalidAppCredential.rawValue {
if retryOnInvalidAppCredential {
auth.appCredentialManager.clearCredential()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import Foundation

@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
struct StartMFASignInResponse: AuthRPCResponse {
var responseInfo: AuthProtoStartMFAPhoneResponseInfo?
// var responseInfo: AuthProtoStartMFAPhoneResponseInfo?
private(set) var responseInfo: AuthProtoStartMFAPhoneResponseInfo?

mutating func setFields(dictionary: [String: AnyHashable]) throws {
if let data = dictionary["phoneResponseInfo"] as? [String: AnyHashable] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@
import Foundation

struct SendVerificationCodeResponse: AuthRPCResponse {
var verificationID: String?
// Default value will be overridden when `setField(dictionary:)` is called.
private(set) var verificationID: String = ""

mutating func setFields(dictionary: [String: AnyHashable]) throws {
verificationID = dictionary["sessionInfo"] as? String
guard let verificationID = dictionary["sessionInfo"] as? String else {
throw AuthErrorUtils.unexpectedResponse(deserializedResponse: dictionary)

Check failure on line 23 in FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift

View workflow job for this annotation

GitHub Actions / integration-tests (ObjCApiTests)

'AuthErrorUtils' is only available in iOS 13 or newer

Check failure on line 23 in FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift

View workflow job for this annotation

GitHub Actions / integration-tests (ObjCApiTests)

'AuthErrorUtils' is only available in iOS 13 or newer

Check failure on line 23 in FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift

View workflow job for this annotation

GitHub Actions / integration-tests (ObjCApiTests)

'AuthErrorUtils' is only available in iOS 13 or newer

Check failure on line 23 in FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift

View workflow job for this annotation

GitHub Actions / integration-tests (SwiftApiTests)

'AuthErrorUtils' is only available in iOS 13 or newer

Check failure on line 23 in FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift

View workflow job for this annotation

GitHub Actions / integration-tests (SwiftApiTests)

'AuthErrorUtils' is only available in iOS 13 or newer

Check failure on line 23 in FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift

View workflow job for this annotation

GitHub Actions / integration-tests (SwiftApiTests)

'AuthErrorUtils' is only available in iOS 13 or newer

Check failure on line 23 in FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift

View workflow job for this annotation

GitHub Actions / integration-tests (AuthenticationExampleUITests)

'AuthErrorUtils' is only available in iOS 13 or newer

Check failure on line 23 in FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift

View workflow job for this annotation

GitHub Actions / integration-tests (AuthenticationExampleUITests)

'AuthErrorUtils' is only available in iOS 13 or newer

Check failure on line 23 in FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift

View workflow job for this annotation

GitHub Actions / integration-tests (AuthenticationExampleUITests)

'AuthErrorUtils' is only available in iOS 13 or newer
}
self.verificationID = verificationID
}
}
2 changes: 1 addition & 1 deletion FirebaseAuth/Tests/Unit/RPCBaseTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class RPCBaseTests: XCTestCase {
XCTFail("decodedRequest is not a dictionary")
}
// Dummy response to unblock await.
let _ = try self.rpcIssuer?.respond(withJSON: [:])
let _ = try self.rpcIssuer?.respond(withJSON: ["sessionInfo": "verification_id_123"])
}
let _ = try await AuthBackend.call(with: request)
}
Expand Down
Loading