From 454f3999ce8fd4d21f4b7e17c469c9b872c58741 Mon Sep 17 00:00:00 2001 From: Nick Cooke <36927374+ncooke3@users.noreply.github.com> Date: Tue, 3 Dec 2024 17:58:52 -0500 Subject: [PATCH] [Auth] Use result type to wrap completion handlers internally (#13563) --- FirebaseAuth/Sources/Swift/Auth/Auth.swift | 92 +++++++++---------- .../AuthProvider/PhoneAuthProvider.swift | 13 ++- .../SignIn/StartMFASignInResponse.swift | 2 +- .../RPC/SendVerificationTokenResponse.swift | 2 +- .../MultiFactor/MultiFactorResolver.swift | 2 +- 5 files changed, 55 insertions(+), 56 deletions(-) diff --git a/FirebaseAuth/Sources/Swift/Auth/Auth.swift b/FirebaseAuth/Sources/Swift/Auth/Auth.swift index b8abba0a933..27aeccf4ece 100644 --- a/FirebaseAuth/Sources/Swift/Auth/Auth.swift +++ b/FirebaseAuth/Sources/Swift/Auth/Auth.swift @@ -300,9 +300,9 @@ extension Auth: AuthInterop { Task { do { let response = try await self.backend.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)) } } } @@ -365,9 +365,9 @@ extension Auth: AuthInterop { withEmail: email, password: password ) - decoratedCallback(authData, nil) + decoratedCallback(.success(authData)) } catch { - decoratedCallback(nil, error) + decoratedCallback(.failure(error)) } } } @@ -463,9 +463,9 @@ extension Auth: AuthInterop { do { let authData = try await self.internalSignInAndRetrieveData(withCredential: credential, isReauthentication: false) - decoratedCallback(authData, nil) + decoratedCallback(.success(authData)) } catch { - decoratedCallback(nil, error) + decoratedCallback(.failure(error)) } } } @@ -544,9 +544,9 @@ extension Auth: AuthInterop { withCredential: credential, isReauthentication: false ) - decoratedCallback(authData, nil) + decoratedCallback(.success(authData)) } catch { - decoratedCallback(nil, error) + decoratedCallback(.failure(error)) } } } @@ -642,9 +642,9 @@ extension Auth: AuthInterop { do { let authData = try await self.internalSignInAndRetrieveData(withCredential: credential, isReauthentication: false) - decoratedCallback(authData, nil) + decoratedCallback(.success(authData)) } catch { - decoratedCallback(nil, error) + decoratedCallback(.failure(error)) } } } @@ -710,7 +710,7 @@ extension Auth: AuthInterop { let decoratedCallback = self.signInFlowAuthDataResultCallback(byDecorating: completion) if let currentUser = self._currentUser, currentUser.isAnonymous { let result = AuthDataResult(withUser: currentUser, additionalUserInfo: nil) - decoratedCallback(result, nil) + decoratedCallback(.success(result)) return } let request = SignUpNewUserRequest(requestConfiguration: self.requestConfiguration) @@ -728,10 +728,11 @@ extension Auth: AuthInterop { profile: nil, username: nil, isNewUser: true) - decoratedCallback(AuthDataResult(withUser: user, additionalUserInfo: additionalUserInfo), - nil) + decoratedCallback( + .success(AuthDataResult(withUser: user, additionalUserInfo: additionalUserInfo)) + ) } catch { - decoratedCallback(nil, error) + decoratedCallback(.failure(error)) } } } @@ -790,10 +791,11 @@ extension Auth: AuthInterop { profile: nil, username: nil, isNewUser: response.isNewUser) - decoratedCallback(AuthDataResult(withUser: user, additionalUserInfo: additionalUserInfo), - nil) + decoratedCallback( + .success(AuthDataResult(withUser: user, additionalUserInfo: additionalUserInfo)) + ) } catch { - decoratedCallback(nil, error) + decoratedCallback(.failure(error)) } } } @@ -866,7 +868,7 @@ extension Auth: AuthInterop { action: AuthRecaptchaAction.signUpPassword) { response, error in if let error { DispatchQueue.main.async { - decoratedCallback(nil, error) + decoratedCallback(.failure(error)) } return } @@ -881,7 +883,8 @@ extension Auth: AuthInterop { func internalCreateUserWithEmail(request: SignUpNewUserRequest, inResponse: SignUpNewUserResponse? = nil, - decoratedCallback: @escaping (AuthDataResult?, Error?) -> Void) { + decoratedCallback: @escaping (Result) + -> Void) { Task { do { var response: SignUpNewUserResponse @@ -900,11 +903,11 @@ extension Auth: AuthInterop { profile: nil, username: nil, isNewUser: true) - decoratedCallback(AuthDataResult(withUser: user, - additionalUserInfo: additionalUserInfo), - nil) + decoratedCallback( + .success(AuthDataResult(withUser: user, additionalUserInfo: additionalUserInfo)) + ) } catch { - decoratedCallback(nil, error) + decoratedCallback(.failure(error)) } } } @@ -1009,9 +1012,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)) } } } @@ -2238,23 +2241,19 @@ extension Auth: AuthInterop { /// Invoked asynchronously on the main thread in the future. /// - Returns: Returns a block that updates the current user. func signInFlowAuthDataResultCallback(byDecorating callback: - ((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) - } - return { authResult, error in - if let error { - authDataCallback(callback, nil, error) - return - } - do { - try self.updateCurrentUser(authResult?.user, byForce: false, savingToDisk: true) - } catch { - authDataCallback(callback, nil, error) - return + ((AuthDataResult?, Error?) -> Void)?) -> (Result) -> Void { + return { result in + switch result { + case let .success(authResult): + do { + try self.updateCurrentUser(authResult.user, byForce: false, savingToDisk: true) + Auth.wrapMainAsync(callback: callback, with: .success(authResult)) + } catch { + Auth.wrapMainAsync(callback: callback, with: .failure(error)) + } + case let .failure(error): + Auth.wrapMainAsync(callback: callback, with: .failure(error)) } - authDataCallback(callback, authResult, nil) } } @@ -2278,11 +2277,12 @@ extension Auth: AuthInterop { } class func wrapMainAsync(callback: ((T?, Error?) -> Void)?, - withParam param: T?, - error: Error?) -> Void { - if let callback { - DispatchQueue.main.async { - callback(param, error) + with result: Result) -> 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) } } } diff --git a/FirebaseAuth/Sources/Swift/AuthProvider/PhoneAuthProvider.swift b/FirebaseAuth/Sources/Swift/AuthProvider/PhoneAuthProvider.swift index 3e72368126c..b50636615cc 100644 --- a/FirebaseAuth/Sources/Swift/AuthProvider/PhoneAuthProvider.swift +++ b/FirebaseAuth/Sources/Swift/AuthProvider/PhoneAuthProvider.swift @@ -265,10 +265,10 @@ import Foundation /// - Parameter phoneNumber: The phone number to be verified. /// - Parameter callback: The callback to be invoked on the global work queue when the flow is /// finished. - func verifyClAndSendVerificationCode(toPhoneNumber phoneNumber: String, - retryOnInvalidAppCredential: Bool, - uiDelegate: AuthUIDelegate?, - auditFallback: Bool = false) async throws + private func verifyClAndSendVerificationCode(toPhoneNumber phoneNumber: String, + retryOnInvalidAppCredential: Bool, + uiDelegate: AuthUIDelegate?, + auditFallback: Bool = false) async throws -> String? { let codeIdentity = try await verifyClient(withUIDelegate: uiDelegate) let request = SendVerificationCodeRequest(phoneNumber: phoneNumber, @@ -350,7 +350,7 @@ import Foundation action: .mfaSmsSignIn ) let response = try await auth.backend.call(with: request) - return response.responseInfo?.sessionInfo + return response.responseInfo.sessionInfo } } catch { // For Audit fallback only after rCE check failed @@ -419,9 +419,8 @@ import Foundation MFAEnrollmentID: session.multiFactorInfo?.uid, signInInfo: startMFARequestInfo, requestConfiguration: auth.requestConfiguration) - let response = try await auth.backend.call(with: request) - return response.responseInfo?.sessionInfo + return response.responseInfo.sessionInfo } } catch { return try await handleVerifyErrorWithRetry( diff --git a/FirebaseAuth/Sources/Swift/Backend/RPC/MultiFactor/SignIn/StartMFASignInResponse.swift b/FirebaseAuth/Sources/Swift/Backend/RPC/MultiFactor/SignIn/StartMFASignInResponse.swift index 291821c58f9..35fc6f0bb4b 100644 --- a/FirebaseAuth/Sources/Swift/Backend/RPC/MultiFactor/SignIn/StartMFASignInResponse.swift +++ b/FirebaseAuth/Sources/Swift/Backend/RPC/MultiFactor/SignIn/StartMFASignInResponse.swift @@ -16,7 +16,7 @@ import Foundation @available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *) struct StartMFASignInResponse: AuthRPCResponse { - var responseInfo: AuthProtoStartMFAPhoneResponseInfo? + let responseInfo: AuthProtoStartMFAPhoneResponseInfo init(dictionary: [String: AnyHashable]) throws { if let data = dictionary["phoneResponseInfo"] as? [String: AnyHashable] { diff --git a/FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift b/FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift index 7b1815c5925..7cbd45a7a44 100644 --- a/FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift +++ b/FirebaseAuth/Sources/Swift/Backend/RPC/SendVerificationTokenResponse.swift @@ -15,7 +15,7 @@ import Foundation struct SendVerificationCodeResponse: AuthRPCResponse { - var verificationID: String? + let verificationID: String? init(dictionary: [String: AnyHashable]) throws { verificationID = dictionary["sessionInfo"] as? String diff --git a/FirebaseAuth/Sources/Swift/MultiFactor/MultiFactorResolver.swift b/FirebaseAuth/Sources/Swift/MultiFactor/MultiFactorResolver.swift index 366ccc02023..223c1f9f5f5 100644 --- a/FirebaseAuth/Sources/Swift/MultiFactor/MultiFactorResolver.swift +++ b/FirebaseAuth/Sources/Swift/MultiFactor/MultiFactorResolver.swift @@ -80,7 +80,7 @@ import Foundation let result = AuthDataResult(withUser: user, additionalUserInfo: nil) let decoratedCallback = self.auth .signInFlowAuthDataResultCallback(byDecorating: completion) - decoratedCallback(result, nil) + decoratedCallback(.success(result)) } catch { if let completion { completion(nil, error)