diff --git a/.github/workflows/e2e_tests.yaml b/.github/workflows/e2e_tests.yaml index 3d5fee4bf3c5..ff814a15b1bf 100644 --- a/.github/workflows/e2e_tests.yaml +++ b/.github/workflows/e2e_tests.yaml @@ -26,7 +26,7 @@ on: jobs: android: - runs-on: macos-13 + runs-on: macos-13-xl timeout-minutes: 45 strategy: matrix: @@ -171,9 +171,6 @@ jobs: # Uncomment following line to have simulator logs printed out for debugging purposes. # xcrun simctl spawn booted log stream --predicate 'eventMessage contains "flutter"' & flutter test integration_test/e2e_test.dart -d "$SIMULATOR" --dart-define=CI=true - FLUTTER_DRIVE_EXIT_CODE=$? - xcrun simctl shutdown "$SIMULATOR" - exit $FLUTTER_DRIVE_EXIT_CODE macos: runs-on: macos-13 @@ -288,7 +285,7 @@ jobs: # workaround we can use the `flutter drive` command. Tracking issue: # https://github.com/flutter/flutter/issues/66264 run: | - chromedriver --port=4444 & + chromedriver --port=4444 --trace-buffer-size=100000 & flutter drive \ --verbose-system-logs \ -d web-server \ diff --git a/docs/auth/federated-auth.md b/docs/auth/federated-auth.md index a999afda070a..40bf76b6fb56 100644 --- a/docs/auth/federated-auth.md +++ b/docs/auth/federated-auth.md @@ -195,7 +195,7 @@ with the Facebook App ID and Secret set. } ``` -Note: Firebase will not set the `User.emailVerified` property +Note: Firebase will not set the `User.isEmailVerified` property to `true` if your user logs in with Facebook. Should your user login using a provider that verifies email (e.g. Google sign-in) then this will be set to true. For further information, see this [issue](https://github.com/firebase/flutterfire/issues/4612#issuecomment-782107867). diff --git a/melos.yaml b/melos.yaml index fa08e3d7dcf9..ab824b9bcdb5 100644 --- a/melos.yaml +++ b/melos.yaml @@ -223,14 +223,14 @@ scripts: melos run generate:pigeon:macos --no-select && \ melos run format --no-select packageFilters: - file-exists: 'pigeons/messages.dart' + fileExists: 'pigeons/messages.dart' description: Generate the pigeon messages for all the supported packages. generate:pigeon:macos: run: | melos exec -- "sed -i '' 's;#import ;#if TARGET_OS_OSX\n#import \n#else\n#import \n#endif;g' ios/Classes/messages.g.m" packageFilters: - file-exists: 'ios/Classes/messages.g.m' + fileExists: 'ios/Classes/messages.g.m' description: Pigeon does not add the condition to import Flutter or FlutterMacOs. Add the condition odm:test: diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/AuthStateChannelStreamHandler.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/AuthStateChannelStreamHandler.java index 759096cd583c..3dd587a4cf62 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/AuthStateChannelStreamHandler.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/AuthStateChannelStreamHandler.java @@ -6,8 +6,6 @@ package io.flutter.plugins.firebase.auth; -import static io.flutter.plugins.firebase.auth.FlutterFirebaseAuthPlugin.parseFirebaseUser; - import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseAuth.AuthStateListener; import com.google.firebase.auth.FirebaseUser; @@ -45,7 +43,7 @@ public void onListen(Object arguments, EventSink events) { if (user == null) { event.put(Constants.USER, null); } else { - event.put(Constants.USER, parseFirebaseUser(user)); + event.put(Constants.USER, PigeonParser.parseFirebaseUser(user).toList()); } events.success(event); diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/Constants.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/Constants.java index 004b5cb12d7a..929bd6d29699 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/Constants.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/Constants.java @@ -8,14 +8,6 @@ public class Constants { - // Base - public static final String TAG = "FLTFirebaseAuthPlugin"; - public static final String ANDROID = "android"; - public static final String IOS = "iOS"; - public static final String MINIMUM_VERSION = "minimumVersion"; - public static final String INSTALL_APP = "installApp"; - public static final String PACKAGE_NAME = "packageName"; - public static final String BUNDLE_ID = "bundleId"; public static final String APP_NAME = "appName"; // Providers @@ -31,70 +23,23 @@ public class Constants { // User public static final String USER = "user"; public static final String EMAIL = "email"; - public static final String NEW_EMAIL = "newEmail"; - public static final String UID = "uid"; - public static final String USERNAME = "username"; - public static final String PASSWORD = "password"; - public static final String NEW_PASSWORD = "newPassword"; - public static final String PREVIOUS_EMAIL = "previousEmail"; - public static final String EMAIL_VERIFIED = "emailVerified"; - public static final String IS_ANONYMOUS = "isAnonymous"; - public static final String IS_NEW_USER = "isNewUser"; - public static final String METADATA = "metadata"; - public static final String DISPLAY_NAME = "displayName"; - public static final String PHONE_NUMBER = "phoneNumber"; - public static final String PHOTO_URL = "photoURL"; - public static final String PROFILE = "profile"; - public static final String ADDITIONAL_USER_INFO = "additionalUserInfo"; - public static final String CREATION_TIME = "creationTime"; - public static final String LAST_SIGN_IN_TIME = "lastSignInTime"; - public static final String TENANT_ID = "tenantId"; - // Auth - public static final String PROVIDERS = "providers"; public static final String PROVIDER_ID = "providerId"; - public static final String PROVIDER_DATA = "providerData"; - public static final String AUTH_CREDENTIAL = "authCredential"; public static final String CREDENTIAL = "credential"; public static final String SECRET = "secret"; - public static final String REFRESH_TOKEN = "refreshToken"; public static final String ID_TOKEN = "idToken"; public static final String TOKEN = "token"; public static final String ACCESS_TOKEN = "accessToken"; - public static final String CODE = "code"; public static final String RAW_NONCE = "rawNonce"; public static final String EMAIL_LINK = "emailLink"; public static final String VERIFICATION_ID = "verificationId"; public static final String SMS_CODE = "smsCode"; - public static final String URL = "url"; - public static final String DYNAMIC_LINK_DOMAIN = "dynamicLinkDomain"; - public static final String LANGUAGE_CODE = "languageCode"; - public static final String CLAIMS = "claims"; - public static final String TIMEOUT = "timeout"; - public static final String AUTH_TIMESTAMP = "authTimestamp"; - public static final String EXPIRATION_TIMESTAMP = "expirationTimestamp"; - public static final String ISSUED_AT_TIMESTAMP = "issuedAtTimestamp"; public static final String SIGN_IN_METHOD = "signInMethod"; - public static final String SIGN_IN_PROVIDER = "signInProvider"; - public static final String SIGN_IN_PROVIDER_SCOPE = "scopes"; - public static final String SIGN_IN_PROVIDER_CUSTOM_PARAMETERS = "customParameters"; - public static final String SIGN_IN_SECOND_FACTOR = "signInSecondFactor"; public static final String FORCE_RESENDING_TOKEN = "forceResendingToken"; - public static final String FORCE_REFRESH = "forceRefresh"; - public static final String TOKEN_ONLY = "tokenOnly"; - public static final String HANDLE_CODE_IN_APP = "handleCodeInApp"; - public static final String ACTION_CODE_SETTINGS = "actionCodeSettings"; - public static final String AUTO_RETRIEVED_SMS_CODE_FOR_TESTING = "autoRetrievedSmsCodeForTesting"; - public static final String HOST = "host"; - public static final String PORT = "port"; public static final String NAME = "name"; - public static final String APP_VERIFICATION_DISABLED_FOR_TESTING = - "appVerificationDisabledForTesting"; - public static final String FORCE_RECAPTCHA_FLOW = "forceRecaptchaFlow"; // MultiFactor public static final String MULTI_FACTOR_HINTS = "multiFactorHints"; public static final String MULTI_FACTOR_SESSION_ID = "multiFactorSessionId"; public static final String MULTI_FACTOR_RESOLVER_ID = "multiFactorResolverId"; - public static final String MULTI_FACTOR_INFO = "multiFactorInfo"; } diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java index f0d4aca85001..cbbadff37990 100755 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java @@ -7,77 +7,40 @@ import static io.flutter.plugins.firebase.core.FlutterFirebasePluginRegistry.registerPlugin; import android.app.Activity; -import android.net.Uri; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.google.android.gms.tasks.Task; import com.google.android.gms.tasks.TaskCompletionSource; -import com.google.android.gms.tasks.Tasks; -import com.google.firebase.FirebaseApiNotAvailableException; import com.google.firebase.FirebaseApp; -import com.google.firebase.FirebaseNetworkException; -import com.google.firebase.FirebaseTooManyRequestsException; -import com.google.firebase.auth.ActionCodeEmailInfo; -import com.google.firebase.auth.ActionCodeInfo; import com.google.firebase.auth.ActionCodeResult; -import com.google.firebase.auth.ActionCodeSettings; -import com.google.firebase.auth.AdditionalUserInfo; import com.google.firebase.auth.AuthCredential; import com.google.firebase.auth.AuthResult; -import com.google.firebase.auth.EmailAuthProvider; -import com.google.firebase.auth.FacebookAuthProvider; import com.google.firebase.auth.FirebaseAuth; -import com.google.firebase.auth.FirebaseAuthException; -import com.google.firebase.auth.FirebaseAuthMultiFactorException; -import com.google.firebase.auth.FirebaseAuthProvider; import com.google.firebase.auth.FirebaseUser; -import com.google.firebase.auth.FirebaseUserMetadata; -import com.google.firebase.auth.GetTokenResult; -import com.google.firebase.auth.GithubAuthProvider; -import com.google.firebase.auth.GoogleAuthProvider; -import com.google.firebase.auth.MultiFactor; -import com.google.firebase.auth.MultiFactorAssertion; import com.google.firebase.auth.MultiFactorInfo; -import com.google.firebase.auth.MultiFactorResolver; import com.google.firebase.auth.MultiFactorSession; -import com.google.firebase.auth.OAuthCredential; import com.google.firebase.auth.OAuthProvider; -import com.google.firebase.auth.PhoneAuthCredential; -import com.google.firebase.auth.PhoneAuthProvider; -import com.google.firebase.auth.PhoneMultiFactorGenerator; import com.google.firebase.auth.PhoneMultiFactorInfo; import com.google.firebase.auth.SignInMethodQueryResult; -import com.google.firebase.auth.TwitterAuthProvider; -import com.google.firebase.auth.UserInfo; -import com.google.firebase.auth.UserProfileChangeRequest; -import com.google.firebase.internal.api.FirebaseNoSignedInUserException; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.EventChannel; import io.flutter.plugin.common.EventChannel.StreamHandler; -import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.MethodChannel.MethodCallHandler; -import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugins.firebase.core.FlutterFirebasePlugin; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.UUID; -import java.util.concurrent.ExecutionException; /** Flutter plugin for Firebase Auth. */ public class FlutterFirebaseAuthPlugin implements FlutterFirebasePlugin, - MethodCallHandler, FlutterPlugin, ActivityAware, - GeneratedAndroidFirebaseAuth.MultiFactorUserHostApi, - GeneratedAndroidFirebaseAuth.MultiFactoResolverHostApi { + GeneratedAndroidFirebaseAuth.FirebaseAuthHostApi { private static final String METHOD_CHANNEL_NAME = "plugins.flutter.io/firebase_auth"; @@ -91,32 +54,16 @@ public class FlutterFirebaseAuthPlugin private final Map streamHandlers = new HashMap<>(); - static Map parseAuthCredential(AuthCredential authCredential) { - if (authCredential == null) { - return null; - } - - int authCredentialHashCode = authCredential.hashCode(); - authCredentials.put(authCredentialHashCode, authCredential); - - Map output = new HashMap<>(); - - output.put(Constants.PROVIDER_ID, authCredential.getProvider()); - output.put(Constants.SIGN_IN_METHOD, authCredential.getSignInMethod()); - output.put(Constants.TOKEN, authCredentialHashCode); - if (authCredential instanceof OAuthCredential) { - output.put(Constants.ACCESS_TOKEN, ((OAuthCredential) authCredential).getAccessToken()); - } - - return output; - } + private final FlutterFirebaseAuthUser firebaseAuthUser = new FlutterFirebaseAuthUser(); + private final FlutterFirebaseMultiFactor firebaseMultiFactor = new FlutterFirebaseMultiFactor(); private void initInstance(BinaryMessenger messenger) { registerPlugin(METHOD_CHANNEL_NAME, this); channel = new MethodChannel(messenger, METHOD_CHANNEL_NAME); - channel.setMethodCallHandler(this); - GeneratedAndroidFirebaseAuth.MultiFactorUserHostApi.setup(messenger, this); - GeneratedAndroidFirebaseAuth.MultiFactoResolverHostApi.setup(messenger, this); + GeneratedAndroidFirebaseAuth.FirebaseAuthHostApi.setup(messenger, this); + GeneratedAndroidFirebaseAuth.FirebaseAuthUserHostApi.setup(messenger, firebaseAuthUser); + GeneratedAndroidFirebaseAuth.MultiFactorUserHostApi.setup(messenger, firebaseMultiFactor); + GeneratedAndroidFirebaseAuth.MultiFactoResolverHostApi.setup(messenger, firebaseMultiFactor); this.messenger = messenger; } @@ -131,9 +78,10 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { channel.setMethodCallHandler(null); channel = null; messenger = null; - GeneratedAndroidFirebaseAuth.MultiFactorUserHostApi.setup(binding.getBinaryMessenger(), null); - GeneratedAndroidFirebaseAuth.MultiFactoResolverHostApi.setup( - binding.getBinaryMessenger(), null); + GeneratedAndroidFirebaseAuth.FirebaseAuthHostApi.setup(messenger, null); + GeneratedAndroidFirebaseAuth.FirebaseAuthUserHostApi.setup(messenger, null); + GeneratedAndroidFirebaseAuth.MultiFactorUserHostApi.setup(null, null); + GeneratedAndroidFirebaseAuth.MultiFactoResolverHostApi.setup(null, null); removeEventListeners(); } @@ -141,21 +89,25 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { @Override public void onAttachedToActivity(ActivityPluginBinding activityPluginBinding) { activity = activityPluginBinding.getActivity(); + firebaseAuthUser.setActivity(activity); } @Override public void onDetachedFromActivityForConfigChanges() { activity = null; + firebaseAuthUser.setActivity(null); } @Override public void onReattachedToActivityForConfigChanges(ActivityPluginBinding activityPluginBinding) { activity = activityPluginBinding.getActivity(); + firebaseAuthUser.setActivity(activity); } @Override public void onDetachedFromActivity() { activity = null; + firebaseAuthUser.setActivity(null); } // Only access activity with this method. @@ -164,388 +116,551 @@ private Activity getActivity() { return activity; } - static FirebaseAuth getAuth(Map arguments) { - String appName = (String) Objects.requireNonNull(arguments.get(Constants.APP_NAME)); - FirebaseApp app = FirebaseApp.getInstance(appName); + static FirebaseAuth getAuthFromPigeon(GeneratedAndroidFirebaseAuth.PigeonFirebaseApp pigeonApp) { + FirebaseApp app = FirebaseApp.getInstance(pigeonApp.getAppName()); FirebaseAuth auth = FirebaseAuth.getInstance(app); - String tenantId = (String) arguments.get(Constants.TENANT_ID); - if (tenantId != null) { - auth.setTenantId(tenantId); + if (pigeonApp.getTenantId() != null) { + auth.setTenantId(pigeonApp.getTenantId()); } return auth; } - private FirebaseUser getCurrentUser(Map arguments) { - String appName = (String) Objects.requireNonNull(arguments.get(Constants.APP_NAME)); - FirebaseApp app = FirebaseApp.getInstance(appName); - return FirebaseAuth.getInstance(app).getCurrentUser(); - } - - private FirebaseUser getCurrentUser(String appName) { - FirebaseApp app = FirebaseApp.getInstance(appName); - return FirebaseAuth.getInstance(app).getCurrentUser(); - } - - private AuthCredential getCredential(Map arguments) - throws FlutterFirebaseAuthPluginException { - @SuppressWarnings("unchecked") - Map credentialMap = - (Map) Objects.requireNonNull(arguments.get(Constants.CREDENTIAL)); - - // If the credential map contains a token, it means a native one has been stored - if (credentialMap.get(Constants.TOKEN) != null) { - int token = (int) credentialMap.get(Constants.TOKEN); - AuthCredential credential = authCredentials.get(token); - - if (credential == null) { - throw FlutterFirebaseAuthPluginException.invalidCredential(); - } - - return credential; - } - - String signInMethod = - (String) Objects.requireNonNull(credentialMap.get(Constants.SIGN_IN_METHOD)); - String secret = (String) credentialMap.get(Constants.SECRET); - String idToken = (String) credentialMap.get(Constants.ID_TOKEN); - String accessToken = (String) credentialMap.get(Constants.ACCESS_TOKEN); - String rawNonce = (String) credentialMap.get(Constants.RAW_NONCE); - - switch (signInMethod) { - case Constants.SIGN_IN_METHOD_PASSWORD: - return EmailAuthProvider.getCredential( - (String) Objects.requireNonNull(credentialMap.get(Constants.EMAIL)), - Objects.requireNonNull(secret)); - case Constants.SIGN_IN_METHOD_EMAIL_LINK: - return EmailAuthProvider.getCredentialWithLink( - (String) Objects.requireNonNull(credentialMap.get(Constants.EMAIL)), - (String) Objects.requireNonNull(credentialMap.get(Constants.EMAIL_LINK))); - case Constants.SIGN_IN_METHOD_FACEBOOK: - return FacebookAuthProvider.getCredential(Objects.requireNonNull(accessToken)); - case Constants.SIGN_IN_METHOD_GOOGLE: - return GoogleAuthProvider.getCredential(idToken, accessToken); - case Constants.SIGN_IN_METHOD_TWITTER: - return TwitterAuthProvider.getCredential( - Objects.requireNonNull(accessToken), Objects.requireNonNull(secret)); - case Constants.SIGN_IN_METHOD_GITHUB: - return GithubAuthProvider.getCredential(Objects.requireNonNull(accessToken)); - case Constants.SIGN_IN_METHOD_PHONE: - { - String verificationId = - (String) Objects.requireNonNull(credentialMap.get(Constants.VERIFICATION_ID)); - String smsCode = (String) Objects.requireNonNull(credentialMap.get(Constants.SMS_CODE)); - return PhoneAuthProvider.getCredential(verificationId, smsCode); - } - case Constants.SIGN_IN_METHOD_OAUTH: - { - String providerId = - (String) Objects.requireNonNull(credentialMap.get(Constants.PROVIDER_ID)); - OAuthProvider.CredentialBuilder builder = OAuthProvider.newCredentialBuilder(providerId); - builder.setAccessToken(Objects.requireNonNull(accessToken)); - if (rawNonce == null) { - builder.setIdToken(Objects.requireNonNull(idToken)); - } else { - builder.setIdTokenWithRawNonce(Objects.requireNonNull(idToken), rawNonce); - } - - return builder.build(); - } - default: - return null; + @Override + public void registerIdTokenListener( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + try { + final FirebaseAuth auth = getAuthFromPigeon(app); + final IdTokenChannelStreamHandler handler = new IdTokenChannelStreamHandler(auth); + final String name = METHOD_CHANNEL_NAME + "/id-token/" + auth.getApp().getName(); + final EventChannel channel = new EventChannel(messenger, name); + channel.setStreamHandler(handler); + streamHandlers.put(channel, handler); + result.success(name); + } catch (Exception e) { + result.error(e); } } - @SuppressWarnings("ConstantConditions") - private Map parseActionCodeResult(@NonNull ActionCodeResult actionCodeResult) { - Map output = new HashMap<>(); - Map data = new HashMap<>(); - - int operation = actionCodeResult.getOperation(); - - switch (operation) { - case ActionCodeResult.PASSWORD_RESET: - output.put("operation", 1); - break; - case ActionCodeResult.VERIFY_EMAIL: - output.put("operation", 2); - break; - case ActionCodeResult.RECOVER_EMAIL: - output.put("operation", 3); - break; - case ActionCodeResult.SIGN_IN_WITH_EMAIL_LINK: - output.put("operation", 4); - break; - case ActionCodeResult.VERIFY_BEFORE_CHANGE_EMAIL: - output.put("operation", 5); - break; - case ActionCodeResult.REVERT_SECOND_FACTOR_ADDITION: - output.put("operation", 6); - break; - default: - // Unknown / Error. - output.put("operation", 0); + @Override + public void registerAuthStateListener( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + try { + final FirebaseAuth auth = getAuthFromPigeon(app); + final AuthStateChannelStreamHandler handler = new AuthStateChannelStreamHandler(auth); + final String name = METHOD_CHANNEL_NAME + "/auth-state/" + auth.getApp().getName(); + final EventChannel channel = new EventChannel(messenger, name); + channel.setStreamHandler(handler); + streamHandlers.put(channel, handler); + result.success(name); + } catch (Exception e) { + result.error(e); } + } - ActionCodeInfo actionCodeInfo = actionCodeResult.getInfo(); - - if (actionCodeInfo != null && operation == ActionCodeResult.VERIFY_EMAIL - || operation == ActionCodeResult.PASSWORD_RESET) { - data.put(Constants.EMAIL, actionCodeInfo.getEmail()); - data.put(Constants.PREVIOUS_EMAIL, null); - } else if (operation == ActionCodeResult.REVERT_SECOND_FACTOR_ADDITION) { - data.put(Constants.EMAIL, null); - data.put(Constants.PREVIOUS_EMAIL, null); - } else if (operation == ActionCodeResult.RECOVER_EMAIL - || operation == ActionCodeResult.VERIFY_BEFORE_CHANGE_EMAIL) { - ActionCodeEmailInfo actionCodeEmailInfo = - (ActionCodeEmailInfo) Objects.requireNonNull(actionCodeInfo); - data.put(Constants.EMAIL, actionCodeEmailInfo.getEmail()); - data.put(Constants.PREVIOUS_EMAIL, actionCodeEmailInfo.getPreviousEmail()); + @Override + public void useEmulator( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String host, + @NonNull Long port, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + try { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + firebaseAuth.useEmulator(host, port.intValue()); + result.success(null); + } catch (Exception e) { + result.error(e); } - - output.put("data", data); - return output; } - private Map parseAuthResult(@NonNull AuthResult authResult) { - Map output = new HashMap<>(); + @Override + public void applyActionCode( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String code, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + firebaseAuth + .applyActionCode(code) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(null); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } - output.put( - Constants.ADDITIONAL_USER_INFO, - parseAdditionalUserInfo(authResult.getAdditionalUserInfo())); - output.put(Constants.AUTH_CREDENTIAL, parseAuthCredential(authResult.getCredential())); - output.put(Constants.USER, parseFirebaseUser(authResult.getUser())); + @Override + public void checkActionCode( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String code, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + firebaseAuth + .checkActionCode(code) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + ActionCodeResult actionCodeInfo = task.getResult(); + result.success(PigeonParser.parseActionCodeResult(actionCodeInfo)); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } - return output; + @Override + public void confirmPasswordReset( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String code, + @NonNull String newPassword, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + + firebaseAuth + .confirmPasswordReset(code, newPassword) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(null); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); } - private Map parseAdditionalUserInfo(AdditionalUserInfo additionalUserInfo) { - if (additionalUserInfo == null) { - return null; - } + @Override + public void createUserWithEmailAndPassword( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String email, + @NonNull String password, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + + firebaseAuth + .createUserWithEmailAndPassword(email, password) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + AuthResult authResult = task.getResult(); + result.success(PigeonParser.parseAuthResult(authResult)); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } - Map output = new HashMap<>(); + @Override + public void signInAnonymously( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + firebaseAuth + .signInAnonymously() + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + AuthResult authResult = task.getResult(); + result.success(PigeonParser.parseAuthResult(authResult)); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } - output.put(Constants.IS_NEW_USER, additionalUserInfo.isNewUser()); - output.put(Constants.PROFILE, additionalUserInfo.getProfile()); - output.put(Constants.PROVIDER_ID, additionalUserInfo.getProviderId()); - output.put(Constants.USERNAME, additionalUserInfo.getUsername()); + @Override + public void signInWithCredential( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull Map input, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + AuthCredential credential = PigeonParser.getCredential(input); + + if (credential == null) { + throw FlutterFirebaseAuthPluginException.invalidCredential(); + } + firebaseAuth + .signInWithCredential(credential) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + AuthResult authResult = task.getResult(); + result.success(PigeonParser.parseAuthResult(authResult)); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } - return output; + @Override + public void signInWithCustomToken( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String token, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + + firebaseAuth + .signInWithCustomToken(token) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + AuthResult authResult = task.getResult(); + result.success(PigeonParser.parseAuthResult(authResult)); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); } - static Map parseFirebaseUser(FirebaseUser firebaseUser) { - if (firebaseUser == null) { - return null; - } + @Override + public void signInWithEmailAndPassword( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String email, + @NonNull String password, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + firebaseAuth + .signInWithEmailAndPassword(email, password) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(PigeonParser.parseAuthResult(task.getResult())); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } - Map output = new HashMap<>(); - Map metadata = new HashMap<>(); - - output.put(Constants.DISPLAY_NAME, firebaseUser.getDisplayName()); - output.put(Constants.EMAIL, firebaseUser.getEmail()); - output.put(Constants.EMAIL_VERIFIED, firebaseUser.isEmailVerified()); - output.put(Constants.IS_ANONYMOUS, firebaseUser.isAnonymous()); - - // TODO(Salakar): add an integration test to check for null, if possible - // See https://github.com/firebase/flutterfire/issues/3643 - final FirebaseUserMetadata userMetadata = firebaseUser.getMetadata(); - if (userMetadata != null) { - metadata.put(Constants.CREATION_TIME, firebaseUser.getMetadata().getCreationTimestamp()); - metadata.put( - Constants.LAST_SIGN_IN_TIME, firebaseUser.getMetadata().getLastSignInTimestamp()); - } - output.put(Constants.METADATA, metadata); - output.put(Constants.PHONE_NUMBER, firebaseUser.getPhoneNumber()); - output.put(Constants.PHOTO_URL, parsePhotoUrl(firebaseUser.getPhotoUrl())); - output.put(Constants.PROVIDER_DATA, parseUserInfoList(firebaseUser.getProviderData())); - output.put(Constants.REFRESH_TOKEN, ""); // native does not provide refresh tokens - output.put(Constants.UID, firebaseUser.getUid()); - output.put(Constants.TENANT_ID, firebaseUser.getTenantId()); - - return output; + @Override + public void signInWithEmailLink( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String email, + @NonNull String emailLink, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + firebaseAuth + .signInWithEmailLink(email, emailLink) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + AuthResult authResult = task.getResult(); + result.success(PigeonParser.parseAuthResult(authResult)); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); } - private static List> parseUserInfoList( - List userInfoList) { - List> output = new ArrayList<>(); + @Override + public void signInWithProvider( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull GeneratedAndroidFirebaseAuth.PigeonSignInProvider signInProvider, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); - if (userInfoList == null) { - return output; + OAuthProvider.Builder provider = OAuthProvider.newBuilder(signInProvider.getProviderId()); + if (signInProvider.getScopes() != null) { + provider.setScopes(signInProvider.getScopes()); } - - for (UserInfo userInfo : new ArrayList(userInfoList)) { - if (userInfo == null) { - continue; - } - if (!FirebaseAuthProvider.PROVIDER_ID.equals(userInfo.getProviderId())) { - output.add(parseUserInfo(userInfo)); - } + if (signInProvider.getCustomParameters() != null) { + provider.addCustomParameters(signInProvider.getCustomParameters()); } - return output; + firebaseAuth + .startActivityForSignInWithProvider(getActivity(), provider.build()) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + AuthResult authResult = task.getResult(); + result.success(PigeonParser.parseAuthResult(authResult)); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); } - private static Map parseUserInfo(@NonNull UserInfo userInfo) { - Map output = new HashMap<>(); - - output.put(Constants.DISPLAY_NAME, userInfo.getDisplayName()); - output.put(Constants.EMAIL, userInfo.getEmail()); - output.put(Constants.PHONE_NUMBER, userInfo.getPhoneNumber()); - output.put(Constants.PHOTO_URL, parsePhotoUrl(userInfo.getPhotoUrl())); - output.put(Constants.PROVIDER_ID, userInfo.getProviderId()); - output.put(Constants.UID, userInfo.getUid()); + @Override + public void signOut( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + try { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + firebaseAuth.signOut(); + result.success(null); + } catch (Exception e) { + result.error(e); + } + } - return output; + @Override + public void fetchSignInMethodsForEmail( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String email, + @NonNull GeneratedAndroidFirebaseAuth.Result> result) { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + + firebaseAuth + .fetchSignInMethodsForEmail(email) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + SignInMethodQueryResult signInMethodQueryResult = task.getResult(); + result.success(signInMethodQueryResult.getSignInMethods()); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); } - private static String parsePhotoUrl(Uri photoUri) { - if (photoUri == null) { - return null; + @Override + public void sendPasswordResetEmail( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String email, + @Nullable GeneratedAndroidFirebaseAuth.PigeonActionCodeSettings actionCodeSettings, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + + if (actionCodeSettings == null) { + firebaseAuth + .sendPasswordResetEmail(email) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(null); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + return; } - String photoUrl = photoUri.toString(); + firebaseAuth + .sendPasswordResetEmail(email, PigeonParser.getActionCodeSettings(actionCodeSettings)) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(null); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } - // Return null if the URL is an empty string - return "".equals(photoUrl) ? null : photoUrl; + @Override + public void sendSignInLinkToEmail( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String email, + @NonNull GeneratedAndroidFirebaseAuth.PigeonActionCodeSettings actionCodeSettings, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + + firebaseAuth + .sendSignInLinkToEmail(email, PigeonParser.getActionCodeSettings(actionCodeSettings)) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(null); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); } - private ActionCodeSettings getActionCodeSettings( - @NonNull Map actionCodeSettingsMap) { - ActionCodeSettings.Builder builder = ActionCodeSettings.newBuilder(); + @Override + public void setLanguageCode( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @Nullable String languageCode, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + try { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); - builder.setUrl((String) Objects.requireNonNull(actionCodeSettingsMap.get(Constants.URL))); + if (languageCode == null) { + firebaseAuth.useAppLanguage(); + } else { + firebaseAuth.setLanguageCode(languageCode); + } - if (actionCodeSettingsMap.get(Constants.DYNAMIC_LINK_DOMAIN) != null) { - builder.setDynamicLinkDomain( - (String) - Objects.requireNonNull(actionCodeSettingsMap.get(Constants.DYNAMIC_LINK_DOMAIN))); + result.success(firebaseAuth.getLanguageCode()); + } catch (Exception e) { + result.error(e); } + } - if (actionCodeSettingsMap.get(Constants.HANDLE_CODE_IN_APP) != null) { - builder.setHandleCodeInApp( - (Boolean) - Objects.requireNonNull(actionCodeSettingsMap.get(Constants.HANDLE_CODE_IN_APP))); - } + @Override + public void setSettings( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseAuthSettings settings, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + try { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); - if (actionCodeSettingsMap.get(Constants.ANDROID) != null) { - @SuppressWarnings("unchecked") - Map android = - (Map) - Objects.requireNonNull(actionCodeSettingsMap.get(Constants.ANDROID)); + firebaseAuth + .getFirebaseAuthSettings() + .setAppVerificationDisabledForTesting(settings.getAppVerificationDisabledForTesting()); - boolean installIfNotAvailable = false; - if (android.get(Constants.INSTALL_APP) != null) { - installIfNotAvailable = - (Boolean) Objects.requireNonNull(android.get(Constants.INSTALL_APP)); - } - String minimumVersion = null; - if (android.get(Constants.MINIMUM_VERSION) != null) { - minimumVersion = (String) android.get(Constants.MINIMUM_VERSION); + if (settings.getForceRecaptchaFlow() != null) { + firebaseAuth + .getFirebaseAuthSettings() + .forceRecaptchaFlowForTesting(settings.getForceRecaptchaFlow()); } - builder.setAndroidPackageName( - (String) Objects.requireNonNull(android.get(Constants.PACKAGE_NAME)), - installIfNotAvailable, - minimumVersion); - } + if (settings.getPhoneNumber() != null && settings.getSmsCode() != null) { + firebaseAuth + .getFirebaseAuthSettings() + .setAutoRetrievedSmsCodeForPhoneNumber( + settings.getPhoneNumber(), settings.getSmsCode()); + } - if (actionCodeSettingsMap.get(Constants.IOS) != null) { - @SuppressWarnings("unchecked") - Map iOS = - (Map) Objects.requireNonNull(actionCodeSettingsMap.get(Constants.IOS)); - builder.setIOSBundleId((String) Objects.requireNonNull(iOS.get(Constants.BUNDLE_ID))); + result.success(null); + } catch (Exception e) { + result.error(e); } - - return builder.build(); } - private Map parseTokenResult(@NonNull GetTokenResult tokenResult) { - Map output = new HashMap<>(); - - output.put(Constants.AUTH_TIMESTAMP, tokenResult.getAuthTimestamp() * 1000); - output.put(Constants.CLAIMS, tokenResult.getClaims()); - output.put(Constants.EXPIRATION_TIMESTAMP, tokenResult.getExpirationTimestamp() * 1000); - output.put(Constants.ISSUED_AT_TIMESTAMP, tokenResult.getIssuedAtTimestamp() * 1000); - output.put(Constants.SIGN_IN_PROVIDER, tokenResult.getSignInProvider()); - output.put(Constants.SIGN_IN_SECOND_FACTOR, tokenResult.getSignInSecondFactor()); - output.put(Constants.TOKEN, tokenResult.getToken()); - - return output; + @Override + public void verifyPasswordResetCode( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String code, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + + firebaseAuth + .verifyPasswordResetCode(code) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(task.getResult()); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); } - private Task registerIdTokenListener(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); + @Override + public void verifyPhoneNumber( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull GeneratedAndroidFirebaseAuth.PigeonVerifyPhoneNumberRequest request, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + try { + String eventChannelName = METHOD_CHANNEL_NAME + "/phone/" + UUID.randomUUID().toString(); + EventChannel channel = new EventChannel(messenger, eventChannelName); - cachedThreadPool.execute( - () -> { - try { - final FirebaseAuth auth = getAuth(arguments); - final IdTokenChannelStreamHandler handler = new IdTokenChannelStreamHandler(auth); - final String name = METHOD_CHANNEL_NAME + "/id-token/" + auth.getApp().getName(); - final EventChannel channel = new EventChannel(messenger, name); - channel.setStreamHandler(handler); - streamHandlers.put(channel, handler); - taskCompletionSource.setResult(name); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); + MultiFactorSession multiFactorSession = null; - return taskCompletionSource.getTask(); - } + if (request.getMultiFactorSessionId() != null) { + multiFactorSession = + FlutterFirebaseMultiFactor.multiFactorSessionMap.get(request.getMultiFactorSessionId()); + } - private Task registerAuthStateListener(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); + final String multiFactorInfoId = request.getMultiFactorInfoId(); + PhoneMultiFactorInfo multiFactorInfo = null; - cachedThreadPool.execute( - () -> { - try { - final FirebaseAuth auth = getAuth(arguments); - final AuthStateChannelStreamHandler handler = new AuthStateChannelStreamHandler(auth); - final String name = METHOD_CHANNEL_NAME + "/auth-state/" + auth.getApp().getName(); - final EventChannel channel = new EventChannel(messenger, name); - channel.setStreamHandler(handler); - streamHandlers.put(channel, handler); - taskCompletionSource.setResult(name); - } catch (Exception e) { - taskCompletionSource.setException(e); + if (multiFactorInfoId != null) { + for (String resolverId : FlutterFirebaseMultiFactor.multiFactorResolverMap.keySet()) { + for (MultiFactorInfo info : + FlutterFirebaseMultiFactor.multiFactorResolverMap.get(resolverId).getHints()) { + if (info.getUid().equals(multiFactorInfoId) && info instanceof PhoneMultiFactorInfo) { + multiFactorInfo = (PhoneMultiFactorInfo) info; + break; + } } - }); + } + } - return taskCompletionSource.getTask(); + PhoneNumberVerificationStreamHandler handler = + new PhoneNumberVerificationStreamHandler( + getActivity(), + app, + request, + multiFactorSession, + multiFactorInfo, + credential -> { + int hashCode = credential.hashCode(); + authCredentials.put(hashCode, credential); + }); + + channel.setStreamHandler(handler); + streamHandlers.put(channel, handler); + + result.success(eventChannelName); + } catch (Exception e) { + result.error(e); + } } - private Task applyActionCode(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); + @Override + public Task> getPluginConstantsForFirebaseApp(FirebaseApp firebaseApp) { + TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); cachedThreadPool.execute( () -> { try { - FirebaseAuth firebaseAuth = getAuth(arguments); - String code = (String) Objects.requireNonNull(arguments.get(Constants.CODE)); - - Tasks.await(firebaseAuth.applyActionCode(code)); - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); + Map constants = new HashMap<>(); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + FirebaseUser firebaseUser = firebaseAuth.getCurrentUser(); + String languageCode = firebaseAuth.getLanguageCode(); - return taskCompletionSource.getTask(); - } + GeneratedAndroidFirebaseAuth.PigeonUserDetails user = + firebaseUser == null ? null : PigeonParser.parseFirebaseUser(firebaseUser); - private Task> checkActionCode(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); + if (languageCode != null) { + constants.put("APP_LANGUAGE_CODE", languageCode); + } - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - String code = (String) Objects.requireNonNull(arguments.get(Constants.CODE)); + if (user != null) { + final Object parsedUser = user.toList(); + constants.put("APP_CURRENT_USER", parsedUser); + } - ActionCodeResult actionCodeResult = Tasks.await(firebaseAuth.checkActionCode(code)); - taskCompletionSource.setResult(parseActionCodeResult(actionCodeResult)); + taskCompletionSource.setResult(constants); } catch (Exception e) { taskCompletionSource.setException(e); } @@ -554,1262 +669,15 @@ private Task> checkActionCode(Map arguments) return taskCompletionSource.getTask(); } - private Task confirmPasswordReset(Map arguments) { + @Override + public Task didReinitializeFirebaseCore() { TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); cachedThreadPool.execute( () -> { try { - FirebaseAuth firebaseAuth = getAuth(arguments); - String code = (String) Objects.requireNonNull(arguments.get(Constants.CODE)); - String newPassword = - (String) Objects.requireNonNull(arguments.get(Constants.NEW_PASSWORD)); - - Tasks.await(firebaseAuth.confirmPasswordReset(code, newPassword)); - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> createUserWithEmailAndPassword(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - String email = (String) Objects.requireNonNull(arguments.get(Constants.EMAIL)); - String password = (String) Objects.requireNonNull(arguments.get(Constants.PASSWORD)); - - AuthResult authResult = - Tasks.await(firebaseAuth.createUserWithEmailAndPassword(email, password)); - - taskCompletionSource.setResult(parseAuthResult(authResult)); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> fetchSignInMethodsForEmail(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - String email = (String) Objects.requireNonNull(arguments.get(Constants.EMAIL)); - - SignInMethodQueryResult result = - Tasks.await(firebaseAuth.fetchSignInMethodsForEmail(email)); - - Map output = new HashMap<>(); - output.put(Constants.PROVIDERS, result.getSignInMethods()); - - taskCompletionSource.setResult(output); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task sendPasswordResetEmail(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - String email = (String) Objects.requireNonNull(arguments.get(Constants.EMAIL)); - Object rawActionCodeSettings = arguments.get(Constants.ACTION_CODE_SETTINGS); - - if (rawActionCodeSettings == null) { - Tasks.await(firebaseAuth.sendPasswordResetEmail(email)); - taskCompletionSource.setResult(null); - return; - } - - @SuppressWarnings("unchecked") - Map actionCodeSettings = (Map) rawActionCodeSettings; - - Tasks.await( - firebaseAuth.sendPasswordResetEmail( - email, getActionCodeSettings(actionCodeSettings))); - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task sendSignInLinkToEmail(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - String email = (String) Objects.requireNonNull(arguments.get(Constants.EMAIL)); - - @SuppressWarnings("unchecked") - Map actionCodeSettings = - (Map) - Objects.requireNonNull(arguments.get(Constants.ACTION_CODE_SETTINGS)); - - Tasks.await( - firebaseAuth.sendSignInLinkToEmail( - email, getActionCodeSettings(actionCodeSettings))); - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> setLanguageCode(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - String languageCode = (String) arguments.get(Constants.LANGUAGE_CODE); - - if (languageCode == null) { - firebaseAuth.useAppLanguage(); - } else { - firebaseAuth.setLanguageCode(languageCode); - } - - taskCompletionSource.setResult( - new HashMap() { - { - put(Constants.LANGUAGE_CODE, firebaseAuth.getLanguageCode()); - } - }); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task setSettings(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - Boolean appVerificationDisabledForTesting = - (Boolean) arguments.get(Constants.APP_VERIFICATION_DISABLED_FOR_TESTING); - Boolean forceRecaptchaFlow = (Boolean) arguments.get(Constants.FORCE_RECAPTCHA_FLOW); - String phoneNumber = (String) arguments.get(Constants.PHONE_NUMBER); - String smsCode = (String) arguments.get(Constants.SMS_CODE); - - if (appVerificationDisabledForTesting != null) { - firebaseAuth - .getFirebaseAuthSettings() - .setAppVerificationDisabledForTesting(appVerificationDisabledForTesting); - } - - if (forceRecaptchaFlow != null) { - firebaseAuth - .getFirebaseAuthSettings() - .forceRecaptchaFlowForTesting(forceRecaptchaFlow); - } - - if (phoneNumber != null && smsCode != null) { - firebaseAuth - .getFirebaseAuthSettings() - .setAutoRetrievedSmsCodeForPhoneNumber(phoneNumber, smsCode); - } - - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> signInAnonymously(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - AuthResult authResult = Tasks.await(firebaseAuth.signInAnonymously()); - taskCompletionSource.setResult(parseAuthResult(authResult)); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> signInWithCredential(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - AuthCredential credential = getCredential(arguments); - - if (credential == null) { - throw FlutterFirebaseAuthPluginException.invalidCredential(); - } - AuthResult authResult = Tasks.await(firebaseAuth.signInWithCredential(credential)); - taskCompletionSource.setResult(parseAuthResult(authResult)); - } catch (Exception e) { - if (e.getCause() instanceof FirebaseAuthMultiFactorException) { - handleMultiFactorException(arguments, taskCompletionSource, e); - } else { - taskCompletionSource.setException(e); - } - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> signInWithCustomToken(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - String token = (String) Objects.requireNonNull(arguments.get(Constants.TOKEN)); - - AuthResult authResult = Tasks.await(firebaseAuth.signInWithCustomToken(token)); - - taskCompletionSource.setResult(parseAuthResult(authResult)); - } catch (Exception e) { - if (e.getCause() instanceof FirebaseAuthMultiFactorException) { - handleMultiFactorException(arguments, taskCompletionSource, e); - } else { - taskCompletionSource.setException(e); - } - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> signInWithEmailAndPassword(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - String email = (String) Objects.requireNonNull(arguments.get(Constants.EMAIL)); - String password = (String) Objects.requireNonNull(arguments.get(Constants.PASSWORD)); - - AuthResult authResult = - Tasks.await(firebaseAuth.signInWithEmailAndPassword(email, password)); - - taskCompletionSource.setResult(parseAuthResult(authResult)); - } catch (Exception e) { - if (e.getCause() instanceof FirebaseAuthMultiFactorException) { - handleMultiFactorException(arguments, taskCompletionSource, e); - } else { - taskCompletionSource.setException(e); - } - } - }); - - return taskCompletionSource.getTask(); - } - - private void handleMultiFactorException( - Map arguments, - TaskCompletionSource> taskCompletionSource, - Exception e) { - final FirebaseAuthMultiFactorException multiFactorException = - (FirebaseAuthMultiFactorException) e.getCause(); - Map output = new HashMap<>(); - - MultiFactorResolver multiFactorResolver = multiFactorException.getResolver(); - final List hints = multiFactorResolver.getHints(); - - final MultiFactorSession session = multiFactorResolver.getSession(); - final String sessionId = UUID.randomUUID().toString(); - multiFactorSessionMap.put(sessionId, session); - - final String resolverId = UUID.randomUUID().toString(); - multiFactorResolverMap.put(resolverId, multiFactorResolver); - - final List> pigeonHints = multiFactorInfoToMap(hints); - - output.put(Constants.APP_NAME, getAuth(arguments).getApp().getName()); - - output.put(Constants.MULTI_FACTOR_HINTS, pigeonHints); - - output.put(Constants.MULTI_FACTOR_SESSION_ID, sessionId); - output.put(Constants.MULTI_FACTOR_RESOLVER_ID, resolverId); - - taskCompletionSource.setException( - new FlutterFirebaseAuthPluginException( - multiFactorException.getErrorCode(), - multiFactorException.getLocalizedMessage(), - output)); - } - - private List multiFactorInfoToPigeon( - List hints) { - List pigeonHints = new ArrayList<>(); - for (MultiFactorInfo info : hints) { - if (info instanceof PhoneMultiFactorInfo) { - pigeonHints.add( - new GeneratedAndroidFirebaseAuth.PigeonMultiFactorInfo.Builder() - .setPhoneNumber(((PhoneMultiFactorInfo) info).getPhoneNumber()) - .setDisplayName(info.getDisplayName()) - .setEnrollmentTimestamp((double) info.getEnrollmentTimestamp()) - .setUid(info.getUid()) - .setFactorId(info.getFactorId()) - .build()); - - } else { - pigeonHints.add( - new GeneratedAndroidFirebaseAuth.PigeonMultiFactorInfo.Builder() - .setDisplayName(info.getDisplayName()) - .setEnrollmentTimestamp((double) info.getEnrollmentTimestamp()) - .setUid(info.getUid()) - .setFactorId(info.getFactorId()) - .build()); - } - } - return pigeonHints; - } - - private List> multiFactorInfoToMap(List hints) { - List> pigeonHints = new ArrayList<>(); - for (GeneratedAndroidFirebaseAuth.PigeonMultiFactorInfo info : multiFactorInfoToPigeon(hints)) { - pigeonHints.add(info.toMap()); - } - return pigeonHints; - } - - private Task> signInWithEmailLink(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - String email = (String) Objects.requireNonNull(arguments.get(Constants.EMAIL)); - String emailLink = (String) Objects.requireNonNull(arguments.get(Constants.EMAIL_LINK)); - - AuthResult authResult = Tasks.await(firebaseAuth.signInWithEmailLink(email, emailLink)); - taskCompletionSource.setResult(parseAuthResult(authResult)); - } catch (Exception e) { - if (e.getCause() instanceof FirebaseAuthMultiFactorException) { - handleMultiFactorException(arguments, taskCompletionSource, e); - } else { - taskCompletionSource.setException(e); - } - } - }); - - return taskCompletionSource.getTask(); - } - - private Task signOut(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - firebaseAuth.signOut(); - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task useEmulator(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - String host = (String) arguments.get(Constants.HOST); - int port = (int) arguments.get(Constants.PORT); - firebaseAuth.useEmulator(host, port); - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> verifyPasswordResetCode(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - String code = (String) Objects.requireNonNull(arguments.get(Constants.CODE)); - - Map output = new HashMap<>(); - output.put(Constants.EMAIL, Tasks.await(firebaseAuth.verifyPasswordResetCode(code))); - - taskCompletionSource.setResult(output); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task verifyPhoneNumber(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - String eventChannelName = - METHOD_CHANNEL_NAME + "/phone/" + UUID.randomUUID().toString(); - EventChannel channel = new EventChannel(messenger, eventChannelName); - - final String multiFactorSessionId = - (String) arguments.get(Constants.MULTI_FACTOR_SESSION_ID); - MultiFactorSession multiFactorSession = null; - - if (multiFactorSessionId != null) { - multiFactorSession = multiFactorSessionMap.get(multiFactorSessionId); - } - - final String multiFactorInfoId = (String) arguments.get(Constants.MULTI_FACTOR_INFO); - PhoneMultiFactorInfo multiFactorInfo = null; - - if (multiFactorInfoId != null) { - for (String resolverId : multiFactorResolverMap.keySet()) { - for (MultiFactorInfo info : multiFactorResolverMap.get(resolverId).getHints()) { - if (info.getUid().equals(multiFactorInfoId) - && info instanceof PhoneMultiFactorInfo) { - multiFactorInfo = (PhoneMultiFactorInfo) info; - break; - } - } - } - } - - PhoneNumberVerificationStreamHandler handler = - new PhoneNumberVerificationStreamHandler( - getActivity(), - arguments, - multiFactorSession, - multiFactorInfo, - credential -> { - int hashCode = credential.hashCode(); - authCredentials.put(hashCode, credential); - }); - - channel.setStreamHandler(handler); - streamHandlers.put(channel, handler); - - taskCompletionSource.setResult(eventChannelName); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task deleteUser(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseUser firebaseUser = getCurrentUser(arguments); - - if (firebaseUser == null) { - taskCompletionSource.setException(FlutterFirebaseAuthPluginException.noUser()); - return; - } - - Tasks.await(firebaseUser.delete()); - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> getIdToken(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseUser firebaseUser = getCurrentUser(arguments); - Boolean forceRefresh = - (Boolean) Objects.requireNonNull(arguments.get(Constants.FORCE_REFRESH)); - Boolean tokenOnly = - (Boolean) Objects.requireNonNull(arguments.get(Constants.TOKEN_ONLY)); - - if (firebaseUser == null) { - taskCompletionSource.setException(FlutterFirebaseAuthPluginException.noUser()); - return; - } - - GetTokenResult tokenResult = Tasks.await(firebaseUser.getIdToken(forceRefresh)); - - if (tokenOnly) { - Map output = new HashMap<>(); - output.put("token", tokenResult.getToken()); - - taskCompletionSource.setResult(output); - } else { - taskCompletionSource.setResult(parseTokenResult(tokenResult)); - } - - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> linkUserWithCredential(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseUser firebaseUser = getCurrentUser(arguments); - AuthCredential credential = getCredential(arguments); - - if (firebaseUser == null) { - taskCompletionSource.setException(FlutterFirebaseAuthPluginException.noUser()); - return; - } - - if (credential == null) { - taskCompletionSource.setException( - FlutterFirebaseAuthPluginException.invalidCredential()); - return; - } - - AuthResult authResult; - - authResult = Tasks.await(firebaseUser.linkWithCredential(credential)); - - taskCompletionSource.setResult(parseAuthResult(authResult)); - } catch (Exception e) { - if (e.getCause() instanceof FirebaseAuthMultiFactorException) { - handleMultiFactorException(arguments, taskCompletionSource, e); - return; - } - String message = e.getMessage(); - - if (message != null - && message.contains("User has already been linked to the given provider.")) { - taskCompletionSource.setException( - FlutterFirebaseAuthPluginException.alreadyLinkedProvider()); - return; - } - - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> reauthenticateUserWithCredential( - Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseUser firebaseUser = getCurrentUser(arguments); - AuthCredential credential = getCredential(arguments); - - if (firebaseUser == null) { - taskCompletionSource.setException(FlutterFirebaseAuthPluginException.noUser()); - return; - } - - if (credential == null) { - taskCompletionSource.setException( - FlutterFirebaseAuthPluginException.invalidCredential()); - return; - } - - AuthResult authResult = - Tasks.await(firebaseUser.reauthenticateAndRetrieveData(credential)); - taskCompletionSource.setResult(parseAuthResult(authResult)); - } catch (Exception e) { - if (e.getCause() instanceof FirebaseAuthMultiFactorException) { - handleMultiFactorException(arguments, taskCompletionSource, e); - } else { - taskCompletionSource.setException(e); - } - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> reloadUser(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseUser firebaseUser = getCurrentUser(arguments); - - if (firebaseUser == null) { - taskCompletionSource.setException(FlutterFirebaseAuthPluginException.noUser()); - return; - } - - // Wait for the user to reload, and send back the updated user - Tasks.await(firebaseUser.reload()); - - taskCompletionSource.setResult(parseFirebaseUser(getCurrentUser(arguments))); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task sendEmailVerification(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseUser firebaseUser = getCurrentUser(arguments); - - if (firebaseUser == null) { - taskCompletionSource.setException(FlutterFirebaseAuthPluginException.noUser()); - return; - } - - Object rawActionCodeSettings = arguments.get(Constants.ACTION_CODE_SETTINGS); - if (rawActionCodeSettings == null) { - Tasks.await(firebaseUser.sendEmailVerification()); - taskCompletionSource.setResult(null); - return; - } - - @SuppressWarnings("unchecked") - Map actionCodeSettings = (Map) rawActionCodeSettings; - - Tasks.await( - firebaseUser.sendEmailVerification(getActionCodeSettings(actionCodeSettings))); - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> unlinkUserProvider(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseUser firebaseUser = getCurrentUser(arguments); - - if (firebaseUser == null) { - taskCompletionSource.setException(FlutterFirebaseAuthPluginException.noUser()); - return; - } - - String providerId = - (String) Objects.requireNonNull(arguments.get(Constants.PROVIDER_ID)); - - AuthResult result = Tasks.await(firebaseUser.unlink(providerId)); - taskCompletionSource.setResult(parseAuthResult(result)); - - } catch (ExecutionException e) { - // If the provider ID was not found an ExecutionException is thrown. - // On web, this is automatically handled, so we catch the specific exception here - // to ensure consistency. - taskCompletionSource.setException(FlutterFirebaseAuthPluginException.noSuchProvider()); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> updateEmail(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseUser firebaseUser = getCurrentUser(arguments); - - if (firebaseUser == null) { - taskCompletionSource.setException(FlutterFirebaseAuthPluginException.noUser()); - return; - } - - String newEmail = (String) Objects.requireNonNull(arguments.get(Constants.NEW_EMAIL)); - Tasks.await(firebaseUser.updateEmail(newEmail)); - Tasks.await(firebaseUser.reload()); - taskCompletionSource.setResult(parseFirebaseUser(firebaseUser)); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> updatePassword(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseUser firebaseUser = getCurrentUser(arguments); - - if (firebaseUser == null) { - taskCompletionSource.setException(FlutterFirebaseAuthPluginException.noUser()); - return; - } - - String newPassword = - (String) Objects.requireNonNull(arguments.get(Constants.NEW_PASSWORD)); - Tasks.await(firebaseUser.updatePassword(newPassword)); - Tasks.await(firebaseUser.reload()); - taskCompletionSource.setResult(parseFirebaseUser(firebaseUser)); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> updatePhoneNumber(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseUser firebaseUser = getCurrentUser(arguments); - - if (firebaseUser == null) { - taskCompletionSource.setException(FlutterFirebaseAuthPluginException.noUser()); - return; - } - - PhoneAuthCredential phoneAuthCredential = - (PhoneAuthCredential) getCredential(arguments); - - if (phoneAuthCredential == null) { - taskCompletionSource.setException( - FlutterFirebaseAuthPluginException.invalidCredential()); - return; - } - - Tasks.await(firebaseUser.updatePhoneNumber(phoneAuthCredential)); - Tasks.await(firebaseUser.reload()); - taskCompletionSource.setResult(parseFirebaseUser(firebaseUser)); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> updateProfile(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseUser firebaseUser = getCurrentUser(arguments); - - if (firebaseUser == null) { - taskCompletionSource.setException(FlutterFirebaseAuthPluginException.noUser()); - return; - } - - @SuppressWarnings("unchecked") - Map profile = - (Map) Objects.requireNonNull(arguments.get(Constants.PROFILE)); - UserProfileChangeRequest.Builder builder = new UserProfileChangeRequest.Builder(); - - if (profile.containsKey(Constants.DISPLAY_NAME)) { - String displayName = profile.get(Constants.DISPLAY_NAME); - builder.setDisplayName(displayName); - } - - if (profile.containsKey(Constants.PHOTO_URL)) { - String photoURL = profile.get(Constants.PHOTO_URL); - if (photoURL != null) { - builder.setPhotoUri(Uri.parse(photoURL)); - } else { - builder.setPhotoUri(null); - } - } - - Tasks.await(firebaseUser.updateProfile(builder.build())); - Tasks.await(firebaseUser.reload()); - taskCompletionSource.setResult(parseFirebaseUser(firebaseUser)); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task verifyBeforeUpdateEmail(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseUser firebaseUser = getCurrentUser(arguments); - - if (firebaseUser == null) { - taskCompletionSource.setException(FlutterFirebaseAuthPluginException.noUser()); - } - - String newEmail = (String) Objects.requireNonNull(arguments.get(Constants.NEW_EMAIL)); - Object rawActionCodeSettings = arguments.get(Constants.ACTION_CODE_SETTINGS); - - if (rawActionCodeSettings == null) { - Tasks.await(firebaseUser.verifyBeforeUpdateEmail(newEmail)); - taskCompletionSource.setResult(null); - return; - } - - @SuppressWarnings("unchecked") - Map actionCodeSettings = (Map) rawActionCodeSettings; - - Tasks.await( - firebaseUser.verifyBeforeUpdateEmail( - newEmail, getActionCodeSettings(actionCodeSettings))); - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - @Override - public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { - final Task methodCallTask; - - switch (call.method) { - case "Auth#registerIdTokenListener": - methodCallTask = registerIdTokenListener(call.arguments()); - break; - case "Auth#registerAuthStateListener": - methodCallTask = registerAuthStateListener(call.arguments()); - break; - case "Auth#applyActionCode": - methodCallTask = applyActionCode(call.arguments()); - break; - case "Auth#checkActionCode": - methodCallTask = checkActionCode(call.arguments()); - break; - case "Auth#confirmPasswordReset": - methodCallTask = confirmPasswordReset(call.arguments()); - break; - case "Auth#createUserWithEmailAndPassword": - methodCallTask = createUserWithEmailAndPassword(call.arguments()); - break; - case "Auth#fetchSignInMethodsForEmail": - methodCallTask = fetchSignInMethodsForEmail(call.arguments()); - break; - case "Auth#sendPasswordResetEmail": - methodCallTask = sendPasswordResetEmail(call.arguments()); - break; - case "Auth#sendSignInLinkToEmail": - methodCallTask = sendSignInLinkToEmail(call.arguments()); - break; - case "Auth#signInWithCredential": - methodCallTask = signInWithCredential(call.arguments()); - break; - case "Auth#setLanguageCode": - methodCallTask = setLanguageCode(call.arguments()); - break; - case "Auth#setSettings": - methodCallTask = setSettings(call.arguments()); - break; - case "Auth#signInAnonymously": - methodCallTask = signInAnonymously(call.arguments()); - break; - case "Auth#signInWithCustomToken": - methodCallTask = signInWithCustomToken(call.arguments()); - break; - case "Auth#signInWithEmailAndPassword": - methodCallTask = signInWithEmailAndPassword(call.arguments()); - break; - case "Auth#signInWithEmailLink": - methodCallTask = signInWithEmailLink(call.arguments()); - break; - case "Auth#signOut": - methodCallTask = signOut(call.arguments()); - break; - case "Auth#useEmulator": - methodCallTask = useEmulator(call.arguments()); - break; - case "Auth#verifyPasswordResetCode": - methodCallTask = verifyPasswordResetCode(call.arguments()); - break; - case "Auth#verifyPhoneNumber": - methodCallTask = verifyPhoneNumber(call.arguments()); - break; - case "Auth#signInWithProvider": - methodCallTask = signInWithProvider(call.arguments()); - break; - case "User#linkWithProvider": - methodCallTask = startActivityForLinkWithProvider(call.arguments()); - break; - case "User#reauthenticateWithProvider": - methodCallTask = reauthenticateWithProvider(call.arguments()); - break; - case "User#delete": - methodCallTask = deleteUser(call.arguments()); - break; - case "User#getIdToken": - methodCallTask = getIdToken(call.arguments()); - break; - case "User#linkWithCredential": - methodCallTask = linkUserWithCredential(call.arguments()); - break; - case "User#reauthenticateUserWithCredential": - methodCallTask = reauthenticateUserWithCredential(call.arguments()); - break; - case "User#reload": - methodCallTask = reloadUser(call.arguments()); - break; - case "User#sendEmailVerification": - methodCallTask = sendEmailVerification(call.arguments()); - break; - case "User#unlink": - methodCallTask = unlinkUserProvider(call.arguments()); - break; - case "User#updateEmail": - methodCallTask = updateEmail(call.arguments()); - break; - case "User#updatePassword": - methodCallTask = updatePassword(call.arguments()); - break; - case "User#updatePhoneNumber": - methodCallTask = updatePhoneNumber(call.arguments()); - break; - case "User#updateProfile": - methodCallTask = updateProfile(call.arguments()); - break; - case "User#verifyBeforeUpdateEmail": - methodCallTask = verifyBeforeUpdateEmail(call.arguments()); - break; - default: - result.notImplemented(); - return; - } - - methodCallTask.addOnCompleteListener( - task -> { - if (task.isSuccessful()) { - result.success(task.getResult()); - } else { - Exception exception = task.getException(); - result.error( - "firebase_auth", - exception != null ? exception.getMessage() : null, - getExceptionDetails(exception)); - } - }); - } - - private Task> startActivityForLinkWithProvider( - Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseUser firebaseUser = getCurrentUser(arguments); - - String providerId = - (String) Objects.requireNonNull(arguments.get(Constants.SIGN_IN_PROVIDER)); - @SuppressWarnings("unchecked") - List scopes = (List) arguments.get(Constants.SIGN_IN_PROVIDER_SCOPE); - @SuppressWarnings("unchecked") - Map customParameters = - (Map) arguments.get(Constants.SIGN_IN_PROVIDER_CUSTOM_PARAMETERS); - - OAuthProvider.Builder provider = OAuthProvider.newBuilder(providerId); - if (scopes != null) { - provider.setScopes(scopes); - } - if (customParameters != null) { - provider.addCustomParameters(customParameters); - } - - AuthResult authResult = - Tasks.await( - firebaseUser.startActivityForLinkWithProvider( - /* activity= */ activity, provider.build())); - taskCompletionSource.setResult(parseAuthResult(authResult)); - } catch (Exception e) { - if (e.getCause() instanceof FirebaseAuthMultiFactorException) { - handleMultiFactorException(arguments, taskCompletionSource, e); - } else { - taskCompletionSource.setException(e); - } - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> reauthenticateWithProvider(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseUser firebaseUser = getCurrentUser(arguments); - - String providerId = - (String) Objects.requireNonNull(arguments.get(Constants.SIGN_IN_PROVIDER)); - @SuppressWarnings("unchecked") - List scopes = (List) arguments.get(Constants.SIGN_IN_PROVIDER_SCOPE); - @SuppressWarnings("unchecked") - Map customParameters = - (Map) arguments.get(Constants.SIGN_IN_PROVIDER_CUSTOM_PARAMETERS); - - OAuthProvider.Builder provider = OAuthProvider.newBuilder(providerId); - if (scopes != null) { - provider.setScopes(scopes); - } - if (customParameters != null) { - provider.addCustomParameters(customParameters); - } - - AuthResult authResult = - Tasks.await( - firebaseUser.startActivityForReauthenticateWithProvider( - /* activity= */ activity, provider.build())); - taskCompletionSource.setResult(parseAuthResult(authResult)); - } catch (Exception e) { - if (e.getCause() instanceof FirebaseAuthMultiFactorException) { - handleMultiFactorException(arguments, taskCompletionSource, e); - } else { - taskCompletionSource.setException(e); - } - } - }); - - return taskCompletionSource.getTask(); - } - - private Task> signInWithProvider(Map arguments) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAuth firebaseAuth = getAuth(arguments); - String providerId = - (String) Objects.requireNonNull(arguments.get(Constants.SIGN_IN_PROVIDER)); - @SuppressWarnings("unchecked") - List scopes = (List) arguments.get(Constants.SIGN_IN_PROVIDER_SCOPE); - @SuppressWarnings("unchecked") - Map customParameters = - (Map) arguments.get(Constants.SIGN_IN_PROVIDER_CUSTOM_PARAMETERS); - - OAuthProvider.Builder provider = OAuthProvider.newBuilder(providerId); - if (scopes != null) { - provider.setScopes(scopes); - } - if (customParameters != null) { - provider.addCustomParameters(customParameters); - } - - AuthResult authResult = - Tasks.await( - firebaseAuth.startActivityForSignInWithProvider( - /* activity= */ activity, provider.build())); - taskCompletionSource.setResult(parseAuthResult(authResult)); - } catch (Exception e) { - if (e.getCause() instanceof FirebaseAuthMultiFactorException) { - handleMultiFactorException(arguments, taskCompletionSource, e); - } else { - taskCompletionSource.setException(e); - } - } - }); - - return taskCompletionSource.getTask(); - } - - @Override - public Task> getPluginConstantsForFirebaseApp(FirebaseApp firebaseApp) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - Map constants = new HashMap<>(); - FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); - FirebaseUser firebaseUser = firebaseAuth.getCurrentUser(); - String languageCode = firebaseAuth.getLanguageCode(); - - Map user = - firebaseUser == null ? null : parseFirebaseUser(firebaseUser); - - if (languageCode != null) { - constants.put("APP_LANGUAGE_CODE", languageCode); - } - - if (user != null) { - constants.put("APP_CURRENT_USER", user); - } - - taskCompletionSource.setResult(constants); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - static Map getExceptionDetails(Exception exception) { - Map details = new HashMap<>(); - - if (exception == null) { - return details; - } - - FlutterFirebaseAuthPluginException authException = null; - - if (exception instanceof FirebaseAuthException) { - authException = new FlutterFirebaseAuthPluginException(exception, exception.getCause()); - } else if (exception.getCause() != null - && exception.getCause() instanceof FirebaseAuthException) { - authException = - new FlutterFirebaseAuthPluginException( - (FirebaseAuthException) exception.getCause(), - exception.getCause().getCause() != null - ? exception.getCause().getCause() - : exception.getCause()); - } else if (exception instanceof FlutterFirebaseAuthPluginException) { - authException = (FlutterFirebaseAuthPluginException) exception; - } - - if (authException != null) { - details.put("code", authException.getCode()); - details.put("message", authException.getMessage()); - details.put("additionalData", authException.getAdditionalData()); - return details; - } - - if (exception instanceof FirebaseNetworkException - || (exception.getCause() != null - && exception.getCause() instanceof FirebaseNetworkException)) { - details.put("code", "network-request-failed"); - details.put( - "message", - "A network error (such as timeout, interrupted connection or unreachable host) has occurred."); - details.put("additionalData", new HashMap<>()); - return details; - } - - if (exception instanceof FirebaseApiNotAvailableException - || (exception.getCause() != null - && exception.getCause() instanceof FirebaseApiNotAvailableException)) { - details.put("code", "api-not-available"); - details.put("message", "The requested API is not available."); - details.put("additionalData", new HashMap<>()); - return details; - } - - if (exception instanceof FirebaseTooManyRequestsException - || (exception.getCause() != null - && exception.getCause() instanceof FirebaseTooManyRequestsException)) { - details.put("code", "too-many-requests"); - details.put( - "message", - "We have blocked all requests from this device due to unusual activity. Try again later."); - details.put("additionalData", new HashMap<>()); - return details; - } - - // Manual message overrides to match other platforms. - if (exception.getMessage() != null - && exception - .getMessage() - .startsWith("Cannot create PhoneAuthCredential without either verificationProof")) { - details.put("code", "invalid-verification-id"); - details.put( - "message", "The verification ID used to create the phone auth credential is invalid."); - details.put("additionalData", new HashMap<>()); - return details; - } - - return details; - } - - @Override - public Task didReinitializeFirebaseCore() { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - removeEventListeners(); - authCredentials.clear(); + removeEventListeners(); + authCredentials.clear(); taskCompletionSource.setResult(null); } catch (Exception e) { taskCompletionSource.setException(e); @@ -1829,169 +697,4 @@ private void removeEventListeners() { } streamHandlers.clear(); } - - // Map an app id to a map of user id to a MultiFactorUser object. - private final Map> multiFactorUserMap = new HashMap<>(); - - // Map an id to a MultiFactorSession object. - private final Map multiFactorSessionMap = new HashMap<>(); - - // Map an id to a MultiFactorSession object. - private final Map multiFactorResolverMap = new HashMap<>(); - - private MultiFactor getAppMultiFactor(@NonNull String appName) - throws FirebaseNoSignedInUserException { - final FirebaseUser currentUser = getCurrentUser(appName); - if (currentUser == null) { - throw new FirebaseNoSignedInUserException("No user is signed in"); - } - if (multiFactorUserMap.get(appName) == null) { - multiFactorUserMap.put(appName, new HashMap<>()); - } - - final Map appMultiFactorUser = multiFactorUserMap.get(appName); - if (appMultiFactorUser.get(currentUser.getUid()) == null) { - appMultiFactorUser.put(currentUser.getUid(), currentUser.getMultiFactor()); - } - - final MultiFactor multiFactor = appMultiFactorUser.get(currentUser.getUid()); - return multiFactor; - } - - @Override - public void enrollPhone( - @NonNull String appName, - @NonNull GeneratedAndroidFirebaseAuth.PigeonPhoneMultiFactorAssertion assertion, - @Nullable String displayName, - GeneratedAndroidFirebaseAuth.Result result) { - final MultiFactor multiFactor; - try { - multiFactor = getAppMultiFactor(appName); - } catch (FirebaseNoSignedInUserException e) { - result.error(e); - return; - } - - PhoneAuthCredential credential = - PhoneAuthProvider.getCredential( - assertion.getVerificationId(), assertion.getVerificationCode()); - - MultiFactorAssertion multiFactorAssertion = PhoneMultiFactorGenerator.getAssertion(credential); - - multiFactor - .enroll(multiFactorAssertion, displayName) - .addOnCompleteListener( - task -> { - if (task.isSuccessful()) { - result.success(null); - } else { - result.error(task.getException()); - } - }); - } - - @Override - public void getSession( - @NonNull String appName, - GeneratedAndroidFirebaseAuth.Result - result) { - final MultiFactor multiFactor; - try { - multiFactor = getAppMultiFactor(appName); - } catch (FirebaseNoSignedInUserException e) { - result.error(e); - return; - } - - multiFactor - .getSession() - .addOnCompleteListener( - task -> { - if (task.isSuccessful()) { - final MultiFactorSession sessionResult = task.getResult(); - final String id = UUID.randomUUID().toString(); - multiFactorSessionMap.put(id, sessionResult); - result.success( - new GeneratedAndroidFirebaseAuth.PigeonMultiFactorSession.Builder() - .setId(id) - .build()); - } else { - Exception exception = task.getException(); - result.error(exception); - } - }); - } - - @Override - public void unenroll( - @NonNull String appName, - @Nullable String factorUid, - GeneratedAndroidFirebaseAuth.Result result) { - final MultiFactor multiFactor; - try { - multiFactor = getAppMultiFactor(appName); - } catch (FirebaseNoSignedInUserException e) { - result.error(e); - return; - } - - multiFactor - .unenroll(factorUid) - .addOnCompleteListener( - task -> { - if (task.isSuccessful()) { - result.success(null); - } else { - result.error(task.getException()); - } - }); - } - - @Override - public void getEnrolledFactors( - @NonNull String appName, - GeneratedAndroidFirebaseAuth.Result> - result) { - final MultiFactor multiFactor; - try { - multiFactor = getAppMultiFactor(appName); - } catch (FirebaseNoSignedInUserException e) { - result.error(e); - return; - } - - final List factors = multiFactor.getEnrolledFactors(); - - final List resultFactors = - multiFactorInfoToPigeon(factors); - - result.success(resultFactors); - } - - @Override - public void resolveSignIn( - @NonNull String resolverId, - @NonNull GeneratedAndroidFirebaseAuth.PigeonPhoneMultiFactorAssertion assertion, - GeneratedAndroidFirebaseAuth.Result> result) { - final MultiFactorResolver resolver = multiFactorResolverMap.get(resolverId); - - PhoneAuthCredential credential = - PhoneAuthProvider.getCredential( - assertion.getVerificationId(), assertion.getVerificationCode()); - - MultiFactorAssertion multiFactorAssertion = PhoneMultiFactorGenerator.getAssertion(credential); - - resolver - .resolveSignIn(multiFactorAssertion) - .addOnCompleteListener( - task -> { - if (task.isSuccessful()) { - final AuthResult authResult = task.getResult(); - result.success(parseAuthResult(authResult)); - } else { - Exception exception = task.getException(); - result.error(exception); - } - }); - } } diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPluginException.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPluginException.java index c656bdf5605e..278edc35093e 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPluginException.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPluginException.java @@ -6,45 +6,110 @@ package io.flutter.plugins.firebase.auth; -import static io.flutter.plugins.firebase.auth.FlutterFirebaseAuthPlugin.parseAuthCredential; - -import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.google.firebase.FirebaseApiNotAvailableException; +import com.google.firebase.FirebaseNetworkException; +import com.google.firebase.FirebaseTooManyRequestsException; import com.google.firebase.auth.AuthCredential; import com.google.firebase.auth.FirebaseAuthException; +import com.google.firebase.auth.FirebaseAuthMultiFactorException; import com.google.firebase.auth.FirebaseAuthUserCollisionException; import com.google.firebase.auth.FirebaseAuthWeakPasswordException; +import com.google.firebase.auth.MultiFactorInfo; +import com.google.firebase.auth.MultiFactorResolver; +import com.google.firebase.auth.MultiFactorSession; import java.util.HashMap; -import java.util.Locale; +import java.util.List; import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ExecutionException; -public class FlutterFirebaseAuthPluginException extends Exception { +public class FlutterFirebaseAuthPluginException { - private final String code; - private final String message; - private Map additionalData = new HashMap<>(); + static GeneratedAndroidFirebaseAuth.FlutterError parserExceptionToFlutter( + @Nullable Exception nativeException) { + if (nativeException == null) { + return new GeneratedAndroidFirebaseAuth.FlutterError("UNKNOWN", null, null); + } + String code = "UNKNOWN"; - FlutterFirebaseAuthPluginException(@NonNull String code, @NonNull String message) { - super(message, null); + String message = nativeException.getMessage(); + Map additionalData = new HashMap<>(); - this.code = code; - this.message = message; - } + if (nativeException instanceof FirebaseAuthMultiFactorException) { + final FirebaseAuthMultiFactorException multiFactorException = + (FirebaseAuthMultiFactorException) nativeException; + Map output = new HashMap<>(); - FlutterFirebaseAuthPluginException( - @NonNull String code, @NonNull String message, @NonNull Map additionalData) { - super(message, null); + MultiFactorResolver multiFactorResolver = multiFactorException.getResolver(); + final List hints = multiFactorResolver.getHints(); - this.code = code; - this.message = message; - this.additionalData = additionalData; - } + final MultiFactorSession session = multiFactorResolver.getSession(); + final String sessionId = UUID.randomUUID().toString(); + FlutterFirebaseMultiFactor.multiFactorSessionMap.put(sessionId, session); - FlutterFirebaseAuthPluginException(@NonNull Exception nativeException, Throwable cause) { - super(nativeException.getMessage(), cause); + final String resolverId = UUID.randomUUID().toString(); + FlutterFirebaseMultiFactor.multiFactorResolverMap.put(resolverId, multiFactorResolver); - String code = "UNKNOWN"; - String message = nativeException.getMessage(); - Map additionalData = new HashMap<>(); + final List> pigeonHints = PigeonParser.multiFactorInfoToMap(hints); + + output.put( + Constants.APP_NAME, + multiFactorException.getResolver().getFirebaseAuth().getApp().getName()); + + output.put(Constants.MULTI_FACTOR_HINTS, pigeonHints); + + output.put(Constants.MULTI_FACTOR_SESSION_ID, sessionId); + output.put(Constants.MULTI_FACTOR_RESOLVER_ID, resolverId); + + return new GeneratedAndroidFirebaseAuth.FlutterError( + multiFactorException.getErrorCode(), multiFactorException.getLocalizedMessage(), output); + } + + if (nativeException instanceof ExecutionException) { + return FlutterFirebaseAuthPluginException.noSuchProvider(); + } + + if (nativeException instanceof FirebaseNetworkException + || (nativeException.getCause() != null + && nativeException.getCause() instanceof FirebaseNetworkException)) { + return new GeneratedAndroidFirebaseAuth.FlutterError( + "network-request-failed", + "A network error (such as timeout, interrupted connection or unreachable host) has occurred.", + null); + } + + if (nativeException instanceof FirebaseApiNotAvailableException + || (nativeException.getCause() != null + && nativeException.getCause() instanceof FirebaseApiNotAvailableException)) { + return new GeneratedAndroidFirebaseAuth.FlutterError( + "api-not-available", "The requested API is not available.", null); + } + + if (nativeException instanceof FirebaseTooManyRequestsException + || (nativeException.getCause() != null + && nativeException.getCause() instanceof FirebaseTooManyRequestsException)) { + return new GeneratedAndroidFirebaseAuth.FlutterError( + "too-many-requests", + "We have blocked all requests from this device due to unusual activity. Try again later.", + null); + } + + // Manual message overrides to match other platforms. + if (nativeException.getMessage() != null + && nativeException + .getMessage() + .startsWith("Cannot create PhoneAuthCredential without either verificationProof")) { + return new GeneratedAndroidFirebaseAuth.FlutterError( + "invalid-verification-code", + "The verification ID used to create the phone auth credential is invalid.", + null); + } + + if (message != null + && message.contains("User has already been linked to the given provider.")) { + return FlutterFirebaseAuthPluginException.alreadyLinkedProvider(); + } if (nativeException instanceof FirebaseAuthException) { code = ((FirebaseAuthException) nativeException).getErrorCode(); @@ -65,46 +130,32 @@ public class FlutterFirebaseAuthPluginException extends Exception { ((FirebaseAuthUserCollisionException) nativeException).getUpdatedCredential(); if (authCredential != null) { - additionalData.put("authCredential", parseAuthCredential(authCredential)); + additionalData.put("authCredential", PigeonParser.parseAuthCredential(authCredential)); } } - this.code = code; - this.message = message; - this.additionalData = additionalData; + return new GeneratedAndroidFirebaseAuth.FlutterError(code, message, additionalData); } - static FlutterFirebaseAuthPluginException noUser() { - return new FlutterFirebaseAuthPluginException( - "NO_CURRENT_USER", "No user currently signed in."); + static GeneratedAndroidFirebaseAuth.FlutterError noUser() { + return new GeneratedAndroidFirebaseAuth.FlutterError( + "NO_CURRENT_USER", "No user currently signed in.", null); } - static FlutterFirebaseAuthPluginException invalidCredential() { - return new FlutterFirebaseAuthPluginException( + static GeneratedAndroidFirebaseAuth.FlutterError invalidCredential() { + return new GeneratedAndroidFirebaseAuth.FlutterError( "INVALID_CREDENTIAL", - "The supplied auth credential is malformed, has expired or is not currently supported."); - } - - static FlutterFirebaseAuthPluginException noSuchProvider() { - return new FlutterFirebaseAuthPluginException( - "NO_SUCH_PROVIDER", "User was not linked to an account with the given provider."); - } - - static FlutterFirebaseAuthPluginException alreadyLinkedProvider() { - return new FlutterFirebaseAuthPluginException( - "PROVIDER_ALREADY_LINKED", "User has already been linked to the given provider."); - } - - public String getCode() { - return code.toLowerCase(Locale.ROOT).replace("error_", "").replace("_", "-"); + "The supplied auth credential is malformed, has expired or is not currently supported.", + null); } - @Override - public String getMessage() { - return message; + static GeneratedAndroidFirebaseAuth.FlutterError noSuchProvider() { + return new GeneratedAndroidFirebaseAuth.FlutterError( + "NO_SUCH_PROVIDER", "User was not linked to an account with the given provider.", null); } - public Map getAdditionalData() { - return additionalData; + static GeneratedAndroidFirebaseAuth.FlutterError alreadyLinkedProvider() { + return new GeneratedAndroidFirebaseAuth.FlutterError( + "PROVIDER_ALREADY_LINKED", "User has already been linked to the given provider.", null); } } diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthUser.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthUser.java new file mode 100644 index 000000000000..c739e50ae412 --- /dev/null +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthUser.java @@ -0,0 +1,551 @@ +/* + * Copyright 2023, the Chromium project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +package io.flutter.plugins.firebase.auth; + +import android.app.Activity; +import android.net.Uri; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.google.firebase.FirebaseApp; +import com.google.firebase.auth.AuthCredential; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.auth.GetTokenResult; +import com.google.firebase.auth.OAuthProvider; +import com.google.firebase.auth.PhoneAuthCredential; +import com.google.firebase.auth.UserProfileChangeRequest; +import java.util.Map; + +public class FlutterFirebaseAuthUser + implements GeneratedAndroidFirebaseAuth.FirebaseAuthUserHostApi { + + private Activity activity; + + public void setActivity(Activity activity) { + this.activity = activity; + } + + public static FirebaseUser getCurrentUserFromPigeon( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp pigeonApp) { + FirebaseApp app = FirebaseApp.getInstance(pigeonApp.getAppName()); + FirebaseAuth auth = FirebaseAuth.getInstance(app); + if (pigeonApp.getTenantId() != null) { + auth.setTenantId(pigeonApp.getTenantId()); + } + + return auth.getCurrentUser(); + } + + @Override + public void delete( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); + + if (firebaseUser == null) { + result.error(FlutterFirebaseAuthPluginException.noUser()); + return; + } + + firebaseUser + .delete() + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(null); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } + + @Override + public void getIdToken( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull Boolean forceRefresh, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); + + if (firebaseUser == null) { + result.error(FlutterFirebaseAuthPluginException.noUser()); + return; + } + + GetTokenResult tokenResult = + firebaseUser + .getIdToken(forceRefresh) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(PigeonParser.parseTokenResult(task.getResult())); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }) + .getResult(); + } + + @Override + public void linkWithCredential( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull Map input, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); + AuthCredential credential = PigeonParser.getCredential(input); + + if (firebaseUser == null) { + result.error(FlutterFirebaseAuthPluginException.noUser()); + return; + } + + if (credential == null) { + result.error(FlutterFirebaseAuthPluginException.invalidCredential()); + return; + } + + firebaseUser + .linkWithCredential(credential) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(PigeonParser.parseAuthResult(task.getResult())); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } + + @Override + public void linkWithProvider( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull GeneratedAndroidFirebaseAuth.PigeonSignInProvider signInProvider, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); + + OAuthProvider.Builder provider = OAuthProvider.newBuilder(signInProvider.getProviderId()); + if (signInProvider.getScopes() != null) { + provider.setScopes(signInProvider.getScopes()); + } + if (signInProvider.getCustomParameters() != null) { + provider.addCustomParameters(signInProvider.getCustomParameters()); + } + + firebaseUser + .startActivityForLinkWithProvider(activity, provider.build()) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(PigeonParser.parseAuthResult(task.getResult())); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } + + @Override + public void reauthenticateWithCredential( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull Map input, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); + AuthCredential credential = PigeonParser.getCredential(input); + + if (firebaseUser == null) { + result.error(FlutterFirebaseAuthPluginException.noUser()); + return; + } + + if (credential == null) { + result.error(FlutterFirebaseAuthPluginException.invalidCredential()); + return; + } + + firebaseUser + .reauthenticateAndRetrieveData(credential) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(PigeonParser.parseAuthResult(task.getResult())); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } + + @Override + public void reauthenticateWithProvider( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull GeneratedAndroidFirebaseAuth.PigeonSignInProvider signInProvider, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); + + OAuthProvider.Builder provider = OAuthProvider.newBuilder(signInProvider.getProviderId()); + if (signInProvider.getScopes() != null) { + provider.setScopes(signInProvider.getScopes()); + } + if (signInProvider.getCustomParameters() != null) { + provider.addCustomParameters(signInProvider.getCustomParameters()); + } + + firebaseUser + .startActivityForReauthenticateWithProvider(activity, provider.build()) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(PigeonParser.parseAuthResult(task.getResult())); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } + + @Override + public void reload( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); + + if (firebaseUser == null) { + result.error(FlutterFirebaseAuthPluginException.noUser()); + return; + } + + firebaseUser + .reload() + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(PigeonParser.parseFirebaseUser(firebaseUser)); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } + + @Override + public void sendEmailVerification( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @Nullable GeneratedAndroidFirebaseAuth.PigeonActionCodeSettings actionCodeSettings, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); + + if (firebaseUser == null) { + result.error(FlutterFirebaseAuthPluginException.noUser()); + return; + } + + if (actionCodeSettings == null) { + firebaseUser + .sendEmailVerification() + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(null); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + return; + } + + firebaseUser + .sendEmailVerification(PigeonParser.getActionCodeSettings(actionCodeSettings)) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(null); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } + + @Override + public void unlink( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String providerId, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); + + if (firebaseUser == null) { + result.error(FlutterFirebaseAuthPluginException.noUser()); + return; + } + + firebaseUser + .unlink(providerId) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(PigeonParser.parseAuthResult(task.getResult())); + } else { + Exception exception = task.getException(); + if (exception + .getMessage() + .contains("User was not linked to an account with the given provider.")) { + result.error(FlutterFirebaseAuthPluginException.noSuchProvider()); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter(exception)); + } + } + }); + } + + @Override + public void updateEmail( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String newEmail, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); + + if (firebaseUser == null) { + result.error(FlutterFirebaseAuthPluginException.noUser()); + return; + } + + firebaseUser + .updateEmail(newEmail) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + firebaseUser + .reload() + .addOnCompleteListener( + reloadTask -> { + if (reloadTask.isSuccessful()) { + result.success(PigeonParser.parseFirebaseUser(firebaseUser)); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + reloadTask.getException())); + } + }); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } + + @Override + public void updatePassword( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String newPassword, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); + + if (firebaseUser == null) { + result.error(FlutterFirebaseAuthPluginException.noUser()); + return; + } + + firebaseUser + .updatePassword(newPassword) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + firebaseUser + .reload() + .addOnCompleteListener( + reloadTask -> { + if (reloadTask.isSuccessful()) { + result.success(PigeonParser.parseFirebaseUser(firebaseUser)); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + reloadTask.getException())); + } + }); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } + + @Override + public void updatePhoneNumber( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull Map input, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); + + if (firebaseUser == null) { + result.error(FlutterFirebaseAuthPluginException.noUser()); + return; + } + + PhoneAuthCredential phoneAuthCredential = + (PhoneAuthCredential) PigeonParser.getCredential(input); + + if (phoneAuthCredential == null) { + result.error(FlutterFirebaseAuthPluginException.invalidCredential()); + return; + } + + firebaseUser + .updatePhoneNumber(phoneAuthCredential) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + firebaseUser + .reload() + .addOnCompleteListener( + reloadTask -> { + if (reloadTask.isSuccessful()) { + result.success(PigeonParser.parseFirebaseUser(firebaseUser)); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + reloadTask.getException())); + } + }); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } + + @Override + public void updateProfile( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull GeneratedAndroidFirebaseAuth.PigeonUserProfile profile, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); + + if (firebaseUser == null) { + result.error(FlutterFirebaseAuthPluginException.noUser()); + return; + } + + UserProfileChangeRequest.Builder builder = new UserProfileChangeRequest.Builder(); + + if (profile.getDisplayNameChanged()) { + builder.setDisplayName(profile.getDisplayName()); + } + + if (profile.getPhotoUrlChanged()) { + if (profile.getPhotoUrl() != null) { + builder.setPhotoUri(Uri.parse(profile.getPhotoUrl())); + } else { + builder.setPhotoUri(null); + } + } + + firebaseUser + .updateProfile(builder.build()) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + firebaseUser + .reload() + .addOnCompleteListener( + reloadTask -> { + if (reloadTask.isSuccessful()) { + result.success(PigeonParser.parseFirebaseUser(firebaseUser)); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + reloadTask.getException())); + } + }); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } + + @Override + public void verifyBeforeUpdateEmail( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String newEmail, + @Nullable GeneratedAndroidFirebaseAuth.PigeonActionCodeSettings actionCodeSettings, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); + + if (firebaseUser == null) { + result.error(FlutterFirebaseAuthPluginException.noUser()); + return; + } + + if (actionCodeSettings == null) { + firebaseUser + .verifyBeforeUpdateEmail(newEmail) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(null); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + return; + } + + firebaseUser + .verifyBeforeUpdateEmail(newEmail, PigeonParser.getActionCodeSettings(actionCodeSettings)) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(null); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } +} diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseMultiFactor.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseMultiFactor.java new file mode 100644 index 000000000000..d19412d0071e --- /dev/null +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseMultiFactor.java @@ -0,0 +1,212 @@ +/* + * Copyright 2023, the Chromium project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +package io.flutter.plugins.firebase.auth; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.auth.MultiFactor; +import com.google.firebase.auth.MultiFactorAssertion; +import com.google.firebase.auth.MultiFactorInfo; +import com.google.firebase.auth.MultiFactorResolver; +import com.google.firebase.auth.MultiFactorSession; +import com.google.firebase.auth.PhoneAuthCredential; +import com.google.firebase.auth.PhoneAuthProvider; +import com.google.firebase.auth.PhoneMultiFactorGenerator; +import com.google.firebase.internal.api.FirebaseNoSignedInUserException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class FlutterFirebaseMultiFactor + implements GeneratedAndroidFirebaseAuth.MultiFactorUserHostApi, + GeneratedAndroidFirebaseAuth.MultiFactoResolverHostApi { + + // Map an app id to a map of user id to a MultiFactorUser object. + static final Map> multiFactorUserMap = new HashMap<>(); + + // Map an id to a MultiFactorSession object. + static final Map multiFactorSessionMap = new HashMap<>(); + + // Map an id to a MultiFactorResolver object. + static final Map multiFactorResolverMap = new HashMap<>(); + + MultiFactor getAppMultiFactor(@NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app) + throws FirebaseNoSignedInUserException { + final FirebaseUser currentUser = FlutterFirebaseAuthUser.getCurrentUserFromPigeon(app); + if (currentUser == null) { + throw new FirebaseNoSignedInUserException("No user is signed in"); + } + if (multiFactorUserMap.get(app.getAppName()) == null) { + multiFactorUserMap.put(app.getAppName(), new HashMap<>()); + } + + final Map appMultiFactorUser = multiFactorUserMap.get(app.getAppName()); + if (appMultiFactorUser.get(currentUser.getUid()) == null) { + appMultiFactorUser.put(currentUser.getUid(), currentUser.getMultiFactor()); + } + + return appMultiFactorUser.get(currentUser.getUid()); + } + + @Override + public void enrollPhone( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull GeneratedAndroidFirebaseAuth.PigeonPhoneMultiFactorAssertion assertion, + @Nullable String displayName, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + final MultiFactor multiFactor; + try { + multiFactor = getAppMultiFactor(app); + } catch (FirebaseNoSignedInUserException e) { + result.error(e); + return; + } + + PhoneAuthCredential credential = + PhoneAuthProvider.getCredential( + assertion.getVerificationId(), assertion.getVerificationCode()); + + MultiFactorAssertion multiFactorAssertion = PhoneMultiFactorGenerator.getAssertion(credential); + + multiFactor + .enroll(multiFactorAssertion, displayName) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(null); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } + + @Override + public void getSession( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + final MultiFactor multiFactor; + try { + multiFactor = getAppMultiFactor(app); + } catch (FirebaseNoSignedInUserException e) { + result.error(e); + return; + } + + multiFactor + .getSession() + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + final MultiFactorSession sessionResult = task.getResult(); + final String id = UUID.randomUUID().toString(); + multiFactorSessionMap.put(id, sessionResult); + result.success( + new GeneratedAndroidFirebaseAuth.PigeonMultiFactorSession.Builder() + .setId(id) + .build()); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } + + @Override + public void unenroll( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull String factorUid, + @NonNull GeneratedAndroidFirebaseAuth.Result result) { + final MultiFactor multiFactor; + try { + multiFactor = getAppMultiFactor(app); + } catch (FirebaseNoSignedInUserException e) { + result.error(FlutterFirebaseAuthPluginException.parserExceptionToFlutter(e)); + return; + } + + multiFactor + .unenroll(factorUid) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(null); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } + + @Override + public void getEnrolledFactors( + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull + GeneratedAndroidFirebaseAuth.Result< + List> + result) { + final MultiFactor multiFactor; + try { + multiFactor = getAppMultiFactor(app); + } catch (FirebaseNoSignedInUserException e) { + result.error(e); + return; + } + + final List factors = multiFactor.getEnrolledFactors(); + + final List resultFactors = + PigeonParser.multiFactorInfoToPigeon(factors); + + result.success(resultFactors); + } + + @Override + public void resolveSignIn( + @NonNull String resolverId, + @NonNull GeneratedAndroidFirebaseAuth.PigeonPhoneMultiFactorAssertion assertion, + @NonNull + GeneratedAndroidFirebaseAuth.Result + result) { + final MultiFactorResolver resolver = multiFactorResolverMap.get(resolverId); + + if (resolver == null) { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + new Exception("Resolver not found"))); + return; + } + + PhoneAuthCredential credential = + PhoneAuthProvider.getCredential( + assertion.getVerificationId(), assertion.getVerificationCode()); + + MultiFactorAssertion multiFactorAssertion = PhoneMultiFactorGenerator.getAssertion(credential); + + resolver + .resolveSignIn(multiFactorAssertion) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + final AuthResult authResult = task.getResult(); + result.success(PigeonParser.parseAuthResult(authResult)); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } +} diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java index 0691b0598d34..775650c9074d 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java @@ -1,10 +1,10 @@ /* - * Copyright 2022, the Chromium project authors. Please see the AUTHORS file + * Copyright 2023, the Chromium project authors. Please see the AUTHORS file * for details. All rights reserved. Use of this source code is governed by a * BSD-style license that can be found in the LICENSE file. */ -// Autogenerated from Pigeon (v3.2.3), do not edit directly. +// Autogenerated from Pigeon (v9.2.4), do not edit directly. // See also: https://pub.dev/packages/pigeon package io.flutter.plugins.firebase.auth; @@ -19,16 +19,72 @@ import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; /** Generated class from Pigeon. */ -@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression"}) +@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"}) public class GeneratedAndroidFirebaseAuth { + /** Error class for passing custom error details to Flutter via a thrown PlatformException. */ + public static class FlutterError extends RuntimeException { + + /** The error code. */ + public final String code; + + /** The error details. Must be a datatype supported by the api codec. */ + public final Object details; + + public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details) { + super(message); + this.code = code; + this.details = details; + } + } + + @NonNull + protected static ArrayList wrapError(@NonNull Throwable exception) { + ArrayList errorList = new ArrayList(3); + if (exception instanceof FlutterError) { + FlutterError error = (FlutterError) exception; + errorList.add(error.code); + errorList.add(error.getMessage()); + errorList.add(error.details); + } else { + errorList.add(exception.toString()); + errorList.add(exception.getClass().getSimpleName()); + errorList.add( + "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception)); + } + return errorList; + } + + /** The type of operation that generated the action code from calling [checkActionCode]. */ + public enum ActionCodeInfoOperation { + /** Unknown operation. */ + UNKNOWN(0), + /** Password reset code generated via [sendPasswordResetEmail]. */ + PASSWORD_RESET(1), + /** Email verification code generated via [User.sendEmailVerification]. */ + VERIFY_EMAIL(2), + /** Email change revocation code generated via [User.updateEmail]. */ + RECOVER_EMAIL(3), + /** Email sign in code generated via [sendSignInLinkToEmail]. */ + EMAIL_SIGN_IN(4), + /** Verify and change email code generated via [User.verifyBeforeUpdateEmail]. */ + VERIFY_AND_CHANGE_EMAIL(5), + /** Action code for reverting second factor addition. */ + REVERT_SECOND_FACTOR_ADDITION(6); + + final int index; + + private ActionCodeInfoOperation(final int index) { + this.index = index; + } + } + /** Generated class from Pigeon that represents data sent in messages. */ - public static class PigeonMultiFactorSession { + public static final class PigeonMultiFactorSession { private @NonNull String id; public @NonNull String getId() { @@ -42,10 +98,11 @@ public void setId(@NonNull String setterArg) { this.id = setterArg; } - /** Constructor is private to enforce null safety; use Builder. */ - private PigeonMultiFactorSession() {} + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonMultiFactorSession() {} public static final class Builder { + private @Nullable String id; public @NonNull Builder setId(@NonNull String setterArg) { @@ -61,22 +118,22 @@ public static final class Builder { } @NonNull - Map toMap() { - Map toMapResult = new HashMap<>(); - toMapResult.put("id", id); - return toMapResult; + ArrayList toList() { + ArrayList toListResult = new ArrayList(1); + toListResult.add(id); + return toListResult; } - static @NonNull PigeonMultiFactorSession fromMap(@NonNull Map map) { + static @NonNull PigeonMultiFactorSession fromList(@NonNull ArrayList list) { PigeonMultiFactorSession pigeonResult = new PigeonMultiFactorSession(); - Object id = map.get("id"); + Object id = list.get(0); pigeonResult.setId((String) id); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static class PigeonPhoneMultiFactorAssertion { + public static final class PigeonPhoneMultiFactorAssertion { private @NonNull String verificationId; public @NonNull String getVerificationId() { @@ -103,10 +160,11 @@ public void setVerificationCode(@NonNull String setterArg) { this.verificationCode = setterArg; } - /** Constructor is private to enforce null safety; use Builder. */ - private PigeonPhoneMultiFactorAssertion() {} + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonPhoneMultiFactorAssertion() {} public static final class Builder { + private @Nullable String verificationId; public @NonNull Builder setVerificationId(@NonNull String setterArg) { @@ -130,25 +188,25 @@ public static final class Builder { } @NonNull - Map toMap() { - Map toMapResult = new HashMap<>(); - toMapResult.put("verificationId", verificationId); - toMapResult.put("verificationCode", verificationCode); - return toMapResult; + ArrayList toList() { + ArrayList toListResult = new ArrayList(2); + toListResult.add(verificationId); + toListResult.add(verificationCode); + return toListResult; } - static @NonNull PigeonPhoneMultiFactorAssertion fromMap(@NonNull Map map) { + static @NonNull PigeonPhoneMultiFactorAssertion fromList(@NonNull ArrayList list) { PigeonPhoneMultiFactorAssertion pigeonResult = new PigeonPhoneMultiFactorAssertion(); - Object verificationId = map.get("verificationId"); + Object verificationId = list.get(0); pigeonResult.setVerificationId((String) verificationId); - Object verificationCode = map.get("verificationCode"); + Object verificationCode = list.get(1); pigeonResult.setVerificationCode((String) verificationCode); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static class PigeonMultiFactorInfo { + public static final class PigeonMultiFactorInfo { private @Nullable String displayName; public @Nullable String getDisplayName() { @@ -205,10 +263,11 @@ public void setPhoneNumber(@Nullable String setterArg) { this.phoneNumber = setterArg; } - /** Constructor is private to enforce null safety; use Builder. */ - private PigeonMultiFactorInfo() {} + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonMultiFactorInfo() {} public static final class Builder { + private @Nullable String displayName; public @NonNull Builder setDisplayName(@Nullable String setterArg) { @@ -256,446 +315,3708 @@ public static final class Builder { } @NonNull - Map toMap() { - Map toMapResult = new HashMap<>(); - toMapResult.put("displayName", displayName); - toMapResult.put("enrollmentTimestamp", enrollmentTimestamp); - toMapResult.put("factorId", factorId); - toMapResult.put("uid", uid); - toMapResult.put("phoneNumber", phoneNumber); - return toMapResult; + ArrayList toList() { + ArrayList toListResult = new ArrayList(5); + toListResult.add(displayName); + toListResult.add(enrollmentTimestamp); + toListResult.add(factorId); + toListResult.add(uid); + toListResult.add(phoneNumber); + return toListResult; } - static @NonNull PigeonMultiFactorInfo fromMap(@NonNull Map map) { + static @NonNull PigeonMultiFactorInfo fromList(@NonNull ArrayList list) { PigeonMultiFactorInfo pigeonResult = new PigeonMultiFactorInfo(); - Object displayName = map.get("displayName"); + Object displayName = list.get(0); pigeonResult.setDisplayName((String) displayName); - Object enrollmentTimestamp = map.get("enrollmentTimestamp"); + Object enrollmentTimestamp = list.get(1); pigeonResult.setEnrollmentTimestamp((Double) enrollmentTimestamp); - Object factorId = map.get("factorId"); + Object factorId = list.get(2); pigeonResult.setFactorId((String) factorId); - Object uid = map.get("uid"); + Object uid = list.get(3); pigeonResult.setUid((String) uid); - Object phoneNumber = map.get("phoneNumber"); + Object phoneNumber = list.get(4); pigeonResult.setPhoneNumber((String) phoneNumber); return pigeonResult; } } - public interface Result { - void success(T result); + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonFirebaseApp { + private @NonNull String appName; - void error(Throwable error); - } + public @NonNull String getAppName() { + return appName; + } - private static class MultiFactorUserHostApiCodec extends StandardMessageCodec { - public static final MultiFactorUserHostApiCodec INSTANCE = new MultiFactorUserHostApiCodec(); + public void setAppName(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"appName\" is null."); + } + this.appName = setterArg; + } - private MultiFactorUserHostApiCodec() {} + private @Nullable String tenantId; - @Override - protected Object readValueOfType(byte type, ByteBuffer buffer) { - switch (type) { - case (byte) 128: - return PigeonMultiFactorInfo.fromMap((Map) readValue(buffer)); + public @Nullable String getTenantId() { + return tenantId; + } - case (byte) 129: - return PigeonMultiFactorSession.fromMap((Map) readValue(buffer)); + public void setTenantId(@Nullable String setterArg) { + this.tenantId = setterArg; + } - case (byte) 130: - return PigeonPhoneMultiFactorAssertion.fromMap((Map) readValue(buffer)); + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonFirebaseApp() {} - default: - return super.readValueOfType(type, buffer); + public static final class Builder { + + private @Nullable String appName; + + public @NonNull Builder setAppName(@NonNull String setterArg) { + this.appName = setterArg; + return this; } - } - @Override - protected void writeValue(ByteArrayOutputStream stream, Object value) { - if (value instanceof PigeonMultiFactorInfo) { - stream.write(128); - writeValue(stream, ((PigeonMultiFactorInfo) value).toMap()); - } else if (value instanceof PigeonMultiFactorSession) { - stream.write(129); - writeValue(stream, ((PigeonMultiFactorSession) value).toMap()); - } else if (value instanceof PigeonPhoneMultiFactorAssertion) { - stream.write(130); - writeValue(stream, ((PigeonPhoneMultiFactorAssertion) value).toMap()); - } else { - super.writeValue(stream, value); + private @Nullable String tenantId; + + public @NonNull Builder setTenantId(@Nullable String setterArg) { + this.tenantId = setterArg; + return this; + } + + public @NonNull PigeonFirebaseApp build() { + PigeonFirebaseApp pigeonReturn = new PigeonFirebaseApp(); + pigeonReturn.setAppName(appName); + pigeonReturn.setTenantId(tenantId); + return pigeonReturn; } } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(2); + toListResult.add(appName); + toListResult.add(tenantId); + return toListResult; + } + + static @NonNull PigeonFirebaseApp fromList(@NonNull ArrayList list) { + PigeonFirebaseApp pigeonResult = new PigeonFirebaseApp(); + Object appName = list.get(0); + pigeonResult.setAppName((String) appName); + Object tenantId = list.get(1); + pigeonResult.setTenantId((String) tenantId); + return pigeonResult; + } } - /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ - public interface MultiFactorUserHostApi { - void enrollPhone( - @NonNull String appName, - @NonNull PigeonPhoneMultiFactorAssertion assertion, - @Nullable String displayName, - Result result); + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonActionCodeInfo { + private @NonNull ActionCodeInfoOperation operation; - void getSession(@NonNull String appName, Result result); + public @NonNull ActionCodeInfoOperation getOperation() { + return operation; + } - void unenroll(@NonNull String appName, @Nullable String factorUid, Result result); + public void setOperation(@NonNull ActionCodeInfoOperation setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"operation\" is null."); + } + this.operation = setterArg; + } - void getEnrolledFactors(@NonNull String appName, Result> result); + private @NonNull PigeonActionCodeInfoData data; - /** The codec used by MultiFactorUserHostApi. */ - static MessageCodec getCodec() { - return MultiFactorUserHostApiCodec.INSTANCE; + public @NonNull PigeonActionCodeInfoData getData() { + return data; } - /** - * Sets up an instance of `MultiFactorUserHostApi` to handle messages through the - * `binaryMessenger`. - */ - static void setup(BinaryMessenger binaryMessenger, MultiFactorUserHostApi api) { - { - BasicMessageChannel channel = - new BasicMessageChannel<>( - binaryMessenger, - "dev.flutter.pigeon.MultiFactorUserHostApi.enrollPhone", - getCodec()); - if (api != null) { - channel.setMessageHandler( - (message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList) message; - String appNameArg = (String) args.get(0); - if (appNameArg == null) { - throw new NullPointerException("appNameArg unexpectedly null."); - } - PigeonPhoneMultiFactorAssertion assertionArg = - (PigeonPhoneMultiFactorAssertion) args.get(1); - if (assertionArg == null) { - throw new NullPointerException("assertionArg unexpectedly null."); - } - String displayNameArg = (String) args.get(2); - Result resultCallback = - new Result() { - public void success(Void result) { - wrapped.put("result", null); - reply.reply(wrapped); - } - - public void error(Throwable error) { - wrapped.put("error", wrapError(error)); - reply.reply(wrapped); - } - }; - - api.enrollPhone(appNameArg, assertionArg, displayNameArg, resultCallback); - } catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - reply.reply(wrapped); - } - }); - } else { - channel.setMessageHandler(null); - } - } - { - BasicMessageChannel channel = - new BasicMessageChannel<>( - binaryMessenger, - "dev.flutter.pigeon.MultiFactorUserHostApi.getSession", - getCodec()); - if (api != null) { - channel.setMessageHandler( - (message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList) message; - String appNameArg = (String) args.get(0); - if (appNameArg == null) { - throw new NullPointerException("appNameArg unexpectedly null."); - } - Result resultCallback = - new Result() { - public void success(PigeonMultiFactorSession result) { - wrapped.put("result", result); - reply.reply(wrapped); - } - - public void error(Throwable error) { - wrapped.put("error", wrapError(error)); - reply.reply(wrapped); - } - }; - - api.getSession(appNameArg, resultCallback); - } catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - reply.reply(wrapped); - } - }); - } else { - channel.setMessageHandler(null); - } - } - { - BasicMessageChannel channel = - new BasicMessageChannel<>( - binaryMessenger, "dev.flutter.pigeon.MultiFactorUserHostApi.unenroll", getCodec()); - if (api != null) { - channel.setMessageHandler( - (message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList) message; - String appNameArg = (String) args.get(0); - if (appNameArg == null) { - throw new NullPointerException("appNameArg unexpectedly null."); - } - String factorUidArg = (String) args.get(1); - Result resultCallback = - new Result() { - public void success(Void result) { - wrapped.put("result", null); - reply.reply(wrapped); - } - - public void error(Throwable error) { - wrapped.put("error", wrapError(error)); - reply.reply(wrapped); - } - }; - - api.unenroll(appNameArg, factorUidArg, resultCallback); - } catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - reply.reply(wrapped); - } - }); - } else { - channel.setMessageHandler(null); - } - } - { - BasicMessageChannel channel = - new BasicMessageChannel<>( - binaryMessenger, - "dev.flutter.pigeon.MultiFactorUserHostApi.getEnrolledFactors", - getCodec()); - if (api != null) { - channel.setMessageHandler( - (message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList) message; - String appNameArg = (String) args.get(0); - if (appNameArg == null) { - throw new NullPointerException("appNameArg unexpectedly null."); - } - Result> resultCallback = - new Result>() { - public void success(List result) { - wrapped.put("result", result); - reply.reply(wrapped); - } - - public void error(Throwable error) { - wrapped.put("error", wrapError(error)); - reply.reply(wrapped); - } - }; - - api.getEnrolledFactors(appNameArg, resultCallback); - } catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - reply.reply(wrapped); - } - }); - } else { - channel.setMessageHandler(null); - } + public void setData(@NonNull PigeonActionCodeInfoData setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"data\" is null."); } + this.data = setterArg; } - } - private static class MultiFactoResolverHostApiCodec extends StandardMessageCodec { - public static final MultiFactoResolverHostApiCodec INSTANCE = - new MultiFactoResolverHostApiCodec(); + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonActionCodeInfo() {} - private MultiFactoResolverHostApiCodec() {} + public static final class Builder { - @Override - protected Object readValueOfType(byte type, ByteBuffer buffer) { - switch (type) { - case (byte) 128: - return PigeonMultiFactorInfo.fromMap((Map) readValue(buffer)); + private @Nullable ActionCodeInfoOperation operation; - case (byte) 129: - return PigeonMultiFactorSession.fromMap((Map) readValue(buffer)); + public @NonNull Builder setOperation(@NonNull ActionCodeInfoOperation setterArg) { + this.operation = setterArg; + return this; + } - case (byte) 130: - return PigeonPhoneMultiFactorAssertion.fromMap((Map) readValue(buffer)); + private @Nullable PigeonActionCodeInfoData data; - default: - return super.readValueOfType(type, buffer); + public @NonNull Builder setData(@NonNull PigeonActionCodeInfoData setterArg) { + this.data = setterArg; + return this; } - } - @Override - protected void writeValue(ByteArrayOutputStream stream, Object value) { - if (value instanceof PigeonMultiFactorInfo) { - stream.write(128); - writeValue(stream, ((PigeonMultiFactorInfo) value).toMap()); - } else if (value instanceof PigeonMultiFactorSession) { - stream.write(129); - writeValue(stream, ((PigeonMultiFactorSession) value).toMap()); - } else if (value instanceof PigeonPhoneMultiFactorAssertion) { - stream.write(130); - writeValue(stream, ((PigeonPhoneMultiFactorAssertion) value).toMap()); - } else { - super.writeValue(stream, value); + public @NonNull PigeonActionCodeInfo build() { + PigeonActionCodeInfo pigeonReturn = new PigeonActionCodeInfo(); + pigeonReturn.setOperation(operation); + pigeonReturn.setData(data); + return pigeonReturn; } } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(2); + toListResult.add(operation == null ? null : operation.index); + toListResult.add((data == null) ? null : data.toList()); + return toListResult; + } + + static @NonNull PigeonActionCodeInfo fromList(@NonNull ArrayList list) { + PigeonActionCodeInfo pigeonResult = new PigeonActionCodeInfo(); + Object operation = list.get(0); + pigeonResult.setOperation( + operation == null ? null : ActionCodeInfoOperation.values()[(int) operation]); + Object data = list.get(1); + pigeonResult.setData( + (data == null) ? null : PigeonActionCodeInfoData.fromList((ArrayList) data)); + return pigeonResult; + } } - /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ - public interface MultiFactoResolverHostApi { - void resolveSignIn( - @NonNull String resolverId, - @NonNull PigeonPhoneMultiFactorAssertion assertion, - Result> result); + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonActionCodeInfoData { + private @Nullable String email; - /** The codec used by MultiFactoResolverHostApi. */ - static MessageCodec getCodec() { - return MultiFactoResolverHostApiCodec.INSTANCE; + public @Nullable String getEmail() { + return email; } - /** - * Sets up an instance of `MultiFactoResolverHostApi` to handle messages through the - * `binaryMessenger`. - */ - static void setup(BinaryMessenger binaryMessenger, MultiFactoResolverHostApi api) { - { - BasicMessageChannel channel = - new BasicMessageChannel<>( - binaryMessenger, - "dev.flutter.pigeon.MultiFactoResolverHostApi.resolveSignIn", - getCodec()); - if (api != null) { - channel.setMessageHandler( - (message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList) message; - String resolverIdArg = (String) args.get(0); - if (resolverIdArg == null) { - throw new NullPointerException("resolverIdArg unexpectedly null."); - } - PigeonPhoneMultiFactorAssertion assertionArg = - (PigeonPhoneMultiFactorAssertion) args.get(1); - if (assertionArg == null) { - throw new NullPointerException("assertionArg unexpectedly null."); - } - Result> resultCallback = - new Result>() { - public void success(Map result) { - wrapped.put("result", result); - reply.reply(wrapped); - } - - public void error(Throwable error) { - wrapped.put("error", wrapError(error)); - reply.reply(wrapped); - } - }; - - api.resolveSignIn(resolverIdArg, assertionArg, resultCallback); - } catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - reply.reply(wrapped); - } - }); - } else { - channel.setMessageHandler(null); - } - } + public void setEmail(@Nullable String setterArg) { + this.email = setterArg; } - } - private static class GenerateInterfacesCodec extends StandardMessageCodec { - public static final GenerateInterfacesCodec INSTANCE = new GenerateInterfacesCodec(); + private @Nullable String previousEmail; - private GenerateInterfacesCodec() {} + public @Nullable String getPreviousEmail() { + return previousEmail; + } - @Override - protected Object readValueOfType(byte type, ByteBuffer buffer) { - switch (type) { - case (byte) 128: - return PigeonMultiFactorInfo.fromMap((Map) readValue(buffer)); + public void setPreviousEmail(@Nullable String setterArg) { + this.previousEmail = setterArg; + } - default: - return super.readValueOfType(type, buffer); + public static final class Builder { + + private @Nullable String email; + + public @NonNull Builder setEmail(@Nullable String setterArg) { + this.email = setterArg; + return this; } - } - @Override - protected void writeValue(ByteArrayOutputStream stream, Object value) { - if (value instanceof PigeonMultiFactorInfo) { - stream.write(128); - writeValue(stream, ((PigeonMultiFactorInfo) value).toMap()); - } else { - super.writeValue(stream, value); + private @Nullable String previousEmail; + + public @NonNull Builder setPreviousEmail(@Nullable String setterArg) { + this.previousEmail = setterArg; + return this; } - } - } - /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ - public interface GenerateInterfaces { - void generateInterfaces(@NonNull PigeonMultiFactorInfo info); + public @NonNull PigeonActionCodeInfoData build() { + PigeonActionCodeInfoData pigeonReturn = new PigeonActionCodeInfoData(); + pigeonReturn.setEmail(email); + pigeonReturn.setPreviousEmail(previousEmail); + return pigeonReturn; + } + } - /** The codec used by GenerateInterfaces. */ - static MessageCodec getCodec() { - return GenerateInterfacesCodec.INSTANCE; + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(2); + toListResult.add(email); + toListResult.add(previousEmail); + return toListResult; } - /** - * Sets up an instance of `GenerateInterfaces` to handle messages through the `binaryMessenger`. - */ - static void setup(BinaryMessenger binaryMessenger, GenerateInterfaces api) { - { - BasicMessageChannel channel = - new BasicMessageChannel<>( - binaryMessenger, - "dev.flutter.pigeon.GenerateInterfaces.generateInterfaces", - getCodec()); - if (api != null) { - channel.setMessageHandler( - (message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList) message; - PigeonMultiFactorInfo infoArg = (PigeonMultiFactorInfo) args.get(0); - if (infoArg == null) { - throw new NullPointerException("infoArg unexpectedly null."); - } - api.generateInterfaces(infoArg); - wrapped.put("result", null); - } catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - } - reply.reply(wrapped); - }); - } else { - channel.setMessageHandler(null); - } - } + static @NonNull PigeonActionCodeInfoData fromList(@NonNull ArrayList list) { + PigeonActionCodeInfoData pigeonResult = new PigeonActionCodeInfoData(); + Object email = list.get(0); + pigeonResult.setEmail((String) email); + Object previousEmail = list.get(1); + pigeonResult.setPreviousEmail((String) previousEmail); + return pigeonResult; } } - private static Map wrapError(Throwable exception) { - Map errorMap = new HashMap<>(); - errorMap.put("message", exception.toString()); - errorMap.put("code", exception.getClass().getSimpleName()); - errorMap.put( - "details", - "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception)); - return errorMap; + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonUserCredential { + private @Nullable PigeonUserDetails user; + + public @Nullable PigeonUserDetails getUser() { + return user; + } + + public void setUser(@Nullable PigeonUserDetails setterArg) { + this.user = setterArg; + } + + private @Nullable PigeonAdditionalUserInfo additionalUserInfo; + + public @Nullable PigeonAdditionalUserInfo getAdditionalUserInfo() { + return additionalUserInfo; + } + + public void setAdditionalUserInfo(@Nullable PigeonAdditionalUserInfo setterArg) { + this.additionalUserInfo = setterArg; + } + + private @Nullable PigeonAuthCredential credential; + + public @Nullable PigeonAuthCredential getCredential() { + return credential; + } + + public void setCredential(@Nullable PigeonAuthCredential setterArg) { + this.credential = setterArg; + } + + public static final class Builder { + + private @Nullable PigeonUserDetails user; + + public @NonNull Builder setUser(@Nullable PigeonUserDetails setterArg) { + this.user = setterArg; + return this; + } + + private @Nullable PigeonAdditionalUserInfo additionalUserInfo; + + public @NonNull Builder setAdditionalUserInfo(@Nullable PigeonAdditionalUserInfo setterArg) { + this.additionalUserInfo = setterArg; + return this; + } + + private @Nullable PigeonAuthCredential credential; + + public @NonNull Builder setCredential(@Nullable PigeonAuthCredential setterArg) { + this.credential = setterArg; + return this; + } + + public @NonNull PigeonUserCredential build() { + PigeonUserCredential pigeonReturn = new PigeonUserCredential(); + pigeonReturn.setUser(user); + pigeonReturn.setAdditionalUserInfo(additionalUserInfo); + pigeonReturn.setCredential(credential); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(3); + toListResult.add((user == null) ? null : user.toList()); + toListResult.add((additionalUserInfo == null) ? null : additionalUserInfo.toList()); + toListResult.add((credential == null) ? null : credential.toList()); + return toListResult; + } + + static @NonNull PigeonUserCredential fromList(@NonNull ArrayList list) { + PigeonUserCredential pigeonResult = new PigeonUserCredential(); + Object user = list.get(0); + pigeonResult.setUser( + (user == null) ? null : PigeonUserDetails.fromList((ArrayList) user)); + Object additionalUserInfo = list.get(1); + pigeonResult.setAdditionalUserInfo( + (additionalUserInfo == null) + ? null + : PigeonAdditionalUserInfo.fromList((ArrayList) additionalUserInfo)); + Object credential = list.get(2); + pigeonResult.setCredential( + (credential == null) + ? null + : PigeonAuthCredential.fromList((ArrayList) credential)); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonAdditionalUserInfo { + private @NonNull Boolean isNewUser; + + public @NonNull Boolean getIsNewUser() { + return isNewUser; + } + + public void setIsNewUser(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"isNewUser\" is null."); + } + this.isNewUser = setterArg; + } + + private @Nullable String providerId; + + public @Nullable String getProviderId() { + return providerId; + } + + public void setProviderId(@Nullable String setterArg) { + this.providerId = setterArg; + } + + private @Nullable String username; + + public @Nullable String getUsername() { + return username; + } + + public void setUsername(@Nullable String setterArg) { + this.username = setterArg; + } + + private @Nullable Map profile; + + public @Nullable Map getProfile() { + return profile; + } + + public void setProfile(@Nullable Map setterArg) { + this.profile = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonAdditionalUserInfo() {} + + public static final class Builder { + + private @Nullable Boolean isNewUser; + + public @NonNull Builder setIsNewUser(@NonNull Boolean setterArg) { + this.isNewUser = setterArg; + return this; + } + + private @Nullable String providerId; + + public @NonNull Builder setProviderId(@Nullable String setterArg) { + this.providerId = setterArg; + return this; + } + + private @Nullable String username; + + public @NonNull Builder setUsername(@Nullable String setterArg) { + this.username = setterArg; + return this; + } + + private @Nullable Map profile; + + public @NonNull Builder setProfile(@Nullable Map setterArg) { + this.profile = setterArg; + return this; + } + + public @NonNull PigeonAdditionalUserInfo build() { + PigeonAdditionalUserInfo pigeonReturn = new PigeonAdditionalUserInfo(); + pigeonReturn.setIsNewUser(isNewUser); + pigeonReturn.setProviderId(providerId); + pigeonReturn.setUsername(username); + pigeonReturn.setProfile(profile); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(4); + toListResult.add(isNewUser); + toListResult.add(providerId); + toListResult.add(username); + toListResult.add(profile); + return toListResult; + } + + static @NonNull PigeonAdditionalUserInfo fromList(@NonNull ArrayList list) { + PigeonAdditionalUserInfo pigeonResult = new PigeonAdditionalUserInfo(); + Object isNewUser = list.get(0); + pigeonResult.setIsNewUser((Boolean) isNewUser); + Object providerId = list.get(1); + pigeonResult.setProviderId((String) providerId); + Object username = list.get(2); + pigeonResult.setUsername((String) username); + Object profile = list.get(3); + pigeonResult.setProfile((Map) profile); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonAuthCredential { + private @NonNull String providerId; + + public @NonNull String getProviderId() { + return providerId; + } + + public void setProviderId(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"providerId\" is null."); + } + this.providerId = setterArg; + } + + private @NonNull String signInMethod; + + public @NonNull String getSignInMethod() { + return signInMethod; + } + + public void setSignInMethod(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"signInMethod\" is null."); + } + this.signInMethod = setterArg; + } + + private @NonNull Long nativeId; + + public @NonNull Long getNativeId() { + return nativeId; + } + + public void setNativeId(@NonNull Long setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"nativeId\" is null."); + } + this.nativeId = setterArg; + } + + private @Nullable String accessToken; + + public @Nullable String getAccessToken() { + return accessToken; + } + + public void setAccessToken(@Nullable String setterArg) { + this.accessToken = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonAuthCredential() {} + + public static final class Builder { + + private @Nullable String providerId; + + public @NonNull Builder setProviderId(@NonNull String setterArg) { + this.providerId = setterArg; + return this; + } + + private @Nullable String signInMethod; + + public @NonNull Builder setSignInMethod(@NonNull String setterArg) { + this.signInMethod = setterArg; + return this; + } + + private @Nullable Long nativeId; + + public @NonNull Builder setNativeId(@NonNull Long setterArg) { + this.nativeId = setterArg; + return this; + } + + private @Nullable String accessToken; + + public @NonNull Builder setAccessToken(@Nullable String setterArg) { + this.accessToken = setterArg; + return this; + } + + public @NonNull PigeonAuthCredential build() { + PigeonAuthCredential pigeonReturn = new PigeonAuthCredential(); + pigeonReturn.setProviderId(providerId); + pigeonReturn.setSignInMethod(signInMethod); + pigeonReturn.setNativeId(nativeId); + pigeonReturn.setAccessToken(accessToken); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(4); + toListResult.add(providerId); + toListResult.add(signInMethod); + toListResult.add(nativeId); + toListResult.add(accessToken); + return toListResult; + } + + static @NonNull PigeonAuthCredential fromList(@NonNull ArrayList list) { + PigeonAuthCredential pigeonResult = new PigeonAuthCredential(); + Object providerId = list.get(0); + pigeonResult.setProviderId((String) providerId); + Object signInMethod = list.get(1); + pigeonResult.setSignInMethod((String) signInMethod); + Object nativeId = list.get(2); + pigeonResult.setNativeId( + (nativeId == null) + ? null + : ((nativeId instanceof Integer) ? (Integer) nativeId : (Long) nativeId)); + Object accessToken = list.get(3); + pigeonResult.setAccessToken((String) accessToken); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonUserInfo { + private @NonNull String uid; + + public @NonNull String getUid() { + return uid; + } + + public void setUid(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"uid\" is null."); + } + this.uid = setterArg; + } + + private @Nullable String email; + + public @Nullable String getEmail() { + return email; + } + + public void setEmail(@Nullable String setterArg) { + this.email = setterArg; + } + + private @Nullable String displayName; + + public @Nullable String getDisplayName() { + return displayName; + } + + public void setDisplayName(@Nullable String setterArg) { + this.displayName = setterArg; + } + + private @Nullable String photoUrl; + + public @Nullable String getPhotoUrl() { + return photoUrl; + } + + public void setPhotoUrl(@Nullable String setterArg) { + this.photoUrl = setterArg; + } + + private @Nullable String phoneNumber; + + public @Nullable String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(@Nullable String setterArg) { + this.phoneNumber = setterArg; + } + + private @NonNull Boolean isAnonymous; + + public @NonNull Boolean getIsAnonymous() { + return isAnonymous; + } + + public void setIsAnonymous(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"isAnonymous\" is null."); + } + this.isAnonymous = setterArg; + } + + private @NonNull Boolean isEmailVerified; + + public @NonNull Boolean getIsEmailVerified() { + return isEmailVerified; + } + + public void setIsEmailVerified(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"isEmailVerified\" is null."); + } + this.isEmailVerified = setterArg; + } + + private @Nullable String providerId; + + public @Nullable String getProviderId() { + return providerId; + } + + public void setProviderId(@Nullable String setterArg) { + this.providerId = setterArg; + } + + private @Nullable String tenantId; + + public @Nullable String getTenantId() { + return tenantId; + } + + public void setTenantId(@Nullable String setterArg) { + this.tenantId = setterArg; + } + + private @Nullable String refreshToken; + + public @Nullable String getRefreshToken() { + return refreshToken; + } + + public void setRefreshToken(@Nullable String setterArg) { + this.refreshToken = setterArg; + } + + private @Nullable Long creationTimestamp; + + public @Nullable Long getCreationTimestamp() { + return creationTimestamp; + } + + public void setCreationTimestamp(@Nullable Long setterArg) { + this.creationTimestamp = setterArg; + } + + private @Nullable Long lastSignInTimestamp; + + public @Nullable Long getLastSignInTimestamp() { + return lastSignInTimestamp; + } + + public void setLastSignInTimestamp(@Nullable Long setterArg) { + this.lastSignInTimestamp = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonUserInfo() {} + + public static final class Builder { + + private @Nullable String uid; + + public @NonNull Builder setUid(@NonNull String setterArg) { + this.uid = setterArg; + return this; + } + + private @Nullable String email; + + public @NonNull Builder setEmail(@Nullable String setterArg) { + this.email = setterArg; + return this; + } + + private @Nullable String displayName; + + public @NonNull Builder setDisplayName(@Nullable String setterArg) { + this.displayName = setterArg; + return this; + } + + private @Nullable String photoUrl; + + public @NonNull Builder setPhotoUrl(@Nullable String setterArg) { + this.photoUrl = setterArg; + return this; + } + + private @Nullable String phoneNumber; + + public @NonNull Builder setPhoneNumber(@Nullable String setterArg) { + this.phoneNumber = setterArg; + return this; + } + + private @Nullable Boolean isAnonymous; + + public @NonNull Builder setIsAnonymous(@NonNull Boolean setterArg) { + this.isAnonymous = setterArg; + return this; + } + + private @Nullable Boolean isEmailVerified; + + public @NonNull Builder setIsEmailVerified(@NonNull Boolean setterArg) { + this.isEmailVerified = setterArg; + return this; + } + + private @Nullable String providerId; + + public @NonNull Builder setProviderId(@Nullable String setterArg) { + this.providerId = setterArg; + return this; + } + + private @Nullable String tenantId; + + public @NonNull Builder setTenantId(@Nullable String setterArg) { + this.tenantId = setterArg; + return this; + } + + private @Nullable String refreshToken; + + public @NonNull Builder setRefreshToken(@Nullable String setterArg) { + this.refreshToken = setterArg; + return this; + } + + private @Nullable Long creationTimestamp; + + public @NonNull Builder setCreationTimestamp(@Nullable Long setterArg) { + this.creationTimestamp = setterArg; + return this; + } + + private @Nullable Long lastSignInTimestamp; + + public @NonNull Builder setLastSignInTimestamp(@Nullable Long setterArg) { + this.lastSignInTimestamp = setterArg; + return this; + } + + public @NonNull PigeonUserInfo build() { + PigeonUserInfo pigeonReturn = new PigeonUserInfo(); + pigeonReturn.setUid(uid); + pigeonReturn.setEmail(email); + pigeonReturn.setDisplayName(displayName); + pigeonReturn.setPhotoUrl(photoUrl); + pigeonReturn.setPhoneNumber(phoneNumber); + pigeonReturn.setIsAnonymous(isAnonymous); + pigeonReturn.setIsEmailVerified(isEmailVerified); + pigeonReturn.setProviderId(providerId); + pigeonReturn.setTenantId(tenantId); + pigeonReturn.setRefreshToken(refreshToken); + pigeonReturn.setCreationTimestamp(creationTimestamp); + pigeonReturn.setLastSignInTimestamp(lastSignInTimestamp); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(12); + toListResult.add(uid); + toListResult.add(email); + toListResult.add(displayName); + toListResult.add(photoUrl); + toListResult.add(phoneNumber); + toListResult.add(isAnonymous); + toListResult.add(isEmailVerified); + toListResult.add(providerId); + toListResult.add(tenantId); + toListResult.add(refreshToken); + toListResult.add(creationTimestamp); + toListResult.add(lastSignInTimestamp); + return toListResult; + } + + static @NonNull PigeonUserInfo fromList(@NonNull ArrayList list) { + PigeonUserInfo pigeonResult = new PigeonUserInfo(); + Object uid = list.get(0); + pigeonResult.setUid((String) uid); + Object email = list.get(1); + pigeonResult.setEmail((String) email); + Object displayName = list.get(2); + pigeonResult.setDisplayName((String) displayName); + Object photoUrl = list.get(3); + pigeonResult.setPhotoUrl((String) photoUrl); + Object phoneNumber = list.get(4); + pigeonResult.setPhoneNumber((String) phoneNumber); + Object isAnonymous = list.get(5); + pigeonResult.setIsAnonymous((Boolean) isAnonymous); + Object isEmailVerified = list.get(6); + pigeonResult.setIsEmailVerified((Boolean) isEmailVerified); + Object providerId = list.get(7); + pigeonResult.setProviderId((String) providerId); + Object tenantId = list.get(8); + pigeonResult.setTenantId((String) tenantId); + Object refreshToken = list.get(9); + pigeonResult.setRefreshToken((String) refreshToken); + Object creationTimestamp = list.get(10); + pigeonResult.setCreationTimestamp( + (creationTimestamp == null) + ? null + : ((creationTimestamp instanceof Integer) + ? (Integer) creationTimestamp + : (Long) creationTimestamp)); + Object lastSignInTimestamp = list.get(11); + pigeonResult.setLastSignInTimestamp( + (lastSignInTimestamp == null) + ? null + : ((lastSignInTimestamp instanceof Integer) + ? (Integer) lastSignInTimestamp + : (Long) lastSignInTimestamp)); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonUserDetails { + private @NonNull PigeonUserInfo userInfo; + + public @NonNull PigeonUserInfo getUserInfo() { + return userInfo; + } + + public void setUserInfo(@NonNull PigeonUserInfo setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"userInfo\" is null."); + } + this.userInfo = setterArg; + } + + private @NonNull List> providerData; + + public @NonNull List> getProviderData() { + return providerData; + } + + public void setProviderData(@NonNull List> setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"providerData\" is null."); + } + this.providerData = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonUserDetails() {} + + public static final class Builder { + + private @Nullable PigeonUserInfo userInfo; + + public @NonNull Builder setUserInfo(@NonNull PigeonUserInfo setterArg) { + this.userInfo = setterArg; + return this; + } + + private @Nullable List> providerData; + + public @NonNull Builder setProviderData(@NonNull List> setterArg) { + this.providerData = setterArg; + return this; + } + + public @NonNull PigeonUserDetails build() { + PigeonUserDetails pigeonReturn = new PigeonUserDetails(); + pigeonReturn.setUserInfo(userInfo); + pigeonReturn.setProviderData(providerData); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(2); + toListResult.add((userInfo == null) ? null : userInfo.toList()); + toListResult.add(providerData); + return toListResult; + } + + static @NonNull PigeonUserDetails fromList(@NonNull ArrayList list) { + PigeonUserDetails pigeonResult = new PigeonUserDetails(); + Object userInfo = list.get(0); + pigeonResult.setUserInfo( + (userInfo == null) ? null : PigeonUserInfo.fromList((ArrayList) userInfo)); + Object providerData = list.get(1); + pigeonResult.setProviderData((List>) providerData); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonActionCodeSettings { + private @NonNull String url; + + public @NonNull String getUrl() { + return url; + } + + public void setUrl(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"url\" is null."); + } + this.url = setterArg; + } + + private @Nullable String dynamicLinkDomain; + + public @Nullable String getDynamicLinkDomain() { + return dynamicLinkDomain; + } + + public void setDynamicLinkDomain(@Nullable String setterArg) { + this.dynamicLinkDomain = setterArg; + } + + private @NonNull Boolean handleCodeInApp; + + public @NonNull Boolean getHandleCodeInApp() { + return handleCodeInApp; + } + + public void setHandleCodeInApp(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"handleCodeInApp\" is null."); + } + this.handleCodeInApp = setterArg; + } + + private @Nullable String iOSBundleId; + + public @Nullable String getIOSBundleId() { + return iOSBundleId; + } + + public void setIOSBundleId(@Nullable String setterArg) { + this.iOSBundleId = setterArg; + } + + private @Nullable String androidPackageName; + + public @Nullable String getAndroidPackageName() { + return androidPackageName; + } + + public void setAndroidPackageName(@Nullable String setterArg) { + this.androidPackageName = setterArg; + } + + private @NonNull Boolean androidInstallApp; + + public @NonNull Boolean getAndroidInstallApp() { + return androidInstallApp; + } + + public void setAndroidInstallApp(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"androidInstallApp\" is null."); + } + this.androidInstallApp = setterArg; + } + + private @Nullable String androidMinimumVersion; + + public @Nullable String getAndroidMinimumVersion() { + return androidMinimumVersion; + } + + public void setAndroidMinimumVersion(@Nullable String setterArg) { + this.androidMinimumVersion = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonActionCodeSettings() {} + + public static final class Builder { + + private @Nullable String url; + + public @NonNull Builder setUrl(@NonNull String setterArg) { + this.url = setterArg; + return this; + } + + private @Nullable String dynamicLinkDomain; + + public @NonNull Builder setDynamicLinkDomain(@Nullable String setterArg) { + this.dynamicLinkDomain = setterArg; + return this; + } + + private @Nullable Boolean handleCodeInApp; + + public @NonNull Builder setHandleCodeInApp(@NonNull Boolean setterArg) { + this.handleCodeInApp = setterArg; + return this; + } + + private @Nullable String iOSBundleId; + + public @NonNull Builder setIOSBundleId(@Nullable String setterArg) { + this.iOSBundleId = setterArg; + return this; + } + + private @Nullable String androidPackageName; + + public @NonNull Builder setAndroidPackageName(@Nullable String setterArg) { + this.androidPackageName = setterArg; + return this; + } + + private @Nullable Boolean androidInstallApp; + + public @NonNull Builder setAndroidInstallApp(@NonNull Boolean setterArg) { + this.androidInstallApp = setterArg; + return this; + } + + private @Nullable String androidMinimumVersion; + + public @NonNull Builder setAndroidMinimumVersion(@Nullable String setterArg) { + this.androidMinimumVersion = setterArg; + return this; + } + + public @NonNull PigeonActionCodeSettings build() { + PigeonActionCodeSettings pigeonReturn = new PigeonActionCodeSettings(); + pigeonReturn.setUrl(url); + pigeonReturn.setDynamicLinkDomain(dynamicLinkDomain); + pigeonReturn.setHandleCodeInApp(handleCodeInApp); + pigeonReturn.setIOSBundleId(iOSBundleId); + pigeonReturn.setAndroidPackageName(androidPackageName); + pigeonReturn.setAndroidInstallApp(androidInstallApp); + pigeonReturn.setAndroidMinimumVersion(androidMinimumVersion); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(7); + toListResult.add(url); + toListResult.add(dynamicLinkDomain); + toListResult.add(handleCodeInApp); + toListResult.add(iOSBundleId); + toListResult.add(androidPackageName); + toListResult.add(androidInstallApp); + toListResult.add(androidMinimumVersion); + return toListResult; + } + + static @NonNull PigeonActionCodeSettings fromList(@NonNull ArrayList list) { + PigeonActionCodeSettings pigeonResult = new PigeonActionCodeSettings(); + Object url = list.get(0); + pigeonResult.setUrl((String) url); + Object dynamicLinkDomain = list.get(1); + pigeonResult.setDynamicLinkDomain((String) dynamicLinkDomain); + Object handleCodeInApp = list.get(2); + pigeonResult.setHandleCodeInApp((Boolean) handleCodeInApp); + Object iOSBundleId = list.get(3); + pigeonResult.setIOSBundleId((String) iOSBundleId); + Object androidPackageName = list.get(4); + pigeonResult.setAndroidPackageName((String) androidPackageName); + Object androidInstallApp = list.get(5); + pigeonResult.setAndroidInstallApp((Boolean) androidInstallApp); + Object androidMinimumVersion = list.get(6); + pigeonResult.setAndroidMinimumVersion((String) androidMinimumVersion); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonFirebaseAuthSettings { + private @NonNull Boolean appVerificationDisabledForTesting; + + public @NonNull Boolean getAppVerificationDisabledForTesting() { + return appVerificationDisabledForTesting; + } + + public void setAppVerificationDisabledForTesting(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException( + "Nonnull field \"appVerificationDisabledForTesting\" is null."); + } + this.appVerificationDisabledForTesting = setterArg; + } + + private @Nullable String userAccessGroup; + + public @Nullable String getUserAccessGroup() { + return userAccessGroup; + } + + public void setUserAccessGroup(@Nullable String setterArg) { + this.userAccessGroup = setterArg; + } + + private @Nullable String phoneNumber; + + public @Nullable String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(@Nullable String setterArg) { + this.phoneNumber = setterArg; + } + + private @Nullable String smsCode; + + public @Nullable String getSmsCode() { + return smsCode; + } + + public void setSmsCode(@Nullable String setterArg) { + this.smsCode = setterArg; + } + + private @Nullable Boolean forceRecaptchaFlow; + + public @Nullable Boolean getForceRecaptchaFlow() { + return forceRecaptchaFlow; + } + + public void setForceRecaptchaFlow(@Nullable Boolean setterArg) { + this.forceRecaptchaFlow = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonFirebaseAuthSettings() {} + + public static final class Builder { + + private @Nullable Boolean appVerificationDisabledForTesting; + + public @NonNull Builder setAppVerificationDisabledForTesting(@NonNull Boolean setterArg) { + this.appVerificationDisabledForTesting = setterArg; + return this; + } + + private @Nullable String userAccessGroup; + + public @NonNull Builder setUserAccessGroup(@Nullable String setterArg) { + this.userAccessGroup = setterArg; + return this; + } + + private @Nullable String phoneNumber; + + public @NonNull Builder setPhoneNumber(@Nullable String setterArg) { + this.phoneNumber = setterArg; + return this; + } + + private @Nullable String smsCode; + + public @NonNull Builder setSmsCode(@Nullable String setterArg) { + this.smsCode = setterArg; + return this; + } + + private @Nullable Boolean forceRecaptchaFlow; + + public @NonNull Builder setForceRecaptchaFlow(@Nullable Boolean setterArg) { + this.forceRecaptchaFlow = setterArg; + return this; + } + + public @NonNull PigeonFirebaseAuthSettings build() { + PigeonFirebaseAuthSettings pigeonReturn = new PigeonFirebaseAuthSettings(); + pigeonReturn.setAppVerificationDisabledForTesting(appVerificationDisabledForTesting); + pigeonReturn.setUserAccessGroup(userAccessGroup); + pigeonReturn.setPhoneNumber(phoneNumber); + pigeonReturn.setSmsCode(smsCode); + pigeonReturn.setForceRecaptchaFlow(forceRecaptchaFlow); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(5); + toListResult.add(appVerificationDisabledForTesting); + toListResult.add(userAccessGroup); + toListResult.add(phoneNumber); + toListResult.add(smsCode); + toListResult.add(forceRecaptchaFlow); + return toListResult; + } + + static @NonNull PigeonFirebaseAuthSettings fromList(@NonNull ArrayList list) { + PigeonFirebaseAuthSettings pigeonResult = new PigeonFirebaseAuthSettings(); + Object appVerificationDisabledForTesting = list.get(0); + pigeonResult.setAppVerificationDisabledForTesting( + (Boolean) appVerificationDisabledForTesting); + Object userAccessGroup = list.get(1); + pigeonResult.setUserAccessGroup((String) userAccessGroup); + Object phoneNumber = list.get(2); + pigeonResult.setPhoneNumber((String) phoneNumber); + Object smsCode = list.get(3); + pigeonResult.setSmsCode((String) smsCode); + Object forceRecaptchaFlow = list.get(4); + pigeonResult.setForceRecaptchaFlow((Boolean) forceRecaptchaFlow); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonSignInProvider { + private @NonNull String providerId; + + public @NonNull String getProviderId() { + return providerId; + } + + public void setProviderId(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"providerId\" is null."); + } + this.providerId = setterArg; + } + + private @Nullable List scopes; + + public @Nullable List getScopes() { + return scopes; + } + + public void setScopes(@Nullable List setterArg) { + this.scopes = setterArg; + } + + private @Nullable Map customParameters; + + public @Nullable Map getCustomParameters() { + return customParameters; + } + + public void setCustomParameters(@Nullable Map setterArg) { + this.customParameters = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonSignInProvider() {} + + public static final class Builder { + + private @Nullable String providerId; + + public @NonNull Builder setProviderId(@NonNull String setterArg) { + this.providerId = setterArg; + return this; + } + + private @Nullable List scopes; + + public @NonNull Builder setScopes(@Nullable List setterArg) { + this.scopes = setterArg; + return this; + } + + private @Nullable Map customParameters; + + public @NonNull Builder setCustomParameters(@Nullable Map setterArg) { + this.customParameters = setterArg; + return this; + } + + public @NonNull PigeonSignInProvider build() { + PigeonSignInProvider pigeonReturn = new PigeonSignInProvider(); + pigeonReturn.setProviderId(providerId); + pigeonReturn.setScopes(scopes); + pigeonReturn.setCustomParameters(customParameters); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(3); + toListResult.add(providerId); + toListResult.add(scopes); + toListResult.add(customParameters); + return toListResult; + } + + static @NonNull PigeonSignInProvider fromList(@NonNull ArrayList list) { + PigeonSignInProvider pigeonResult = new PigeonSignInProvider(); + Object providerId = list.get(0); + pigeonResult.setProviderId((String) providerId); + Object scopes = list.get(1); + pigeonResult.setScopes((List) scopes); + Object customParameters = list.get(2); + pigeonResult.setCustomParameters((Map) customParameters); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonVerifyPhoneNumberRequest { + private @Nullable String phoneNumber; + + public @Nullable String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(@Nullable String setterArg) { + this.phoneNumber = setterArg; + } + + private @NonNull Long timeout; + + public @NonNull Long getTimeout() { + return timeout; + } + + public void setTimeout(@NonNull Long setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"timeout\" is null."); + } + this.timeout = setterArg; + } + + private @Nullable Long forceResendingToken; + + public @Nullable Long getForceResendingToken() { + return forceResendingToken; + } + + public void setForceResendingToken(@Nullable Long setterArg) { + this.forceResendingToken = setterArg; + } + + private @Nullable String autoRetrievedSmsCodeForTesting; + + public @Nullable String getAutoRetrievedSmsCodeForTesting() { + return autoRetrievedSmsCodeForTesting; + } + + public void setAutoRetrievedSmsCodeForTesting(@Nullable String setterArg) { + this.autoRetrievedSmsCodeForTesting = setterArg; + } + + private @Nullable String multiFactorInfoId; + + public @Nullable String getMultiFactorInfoId() { + return multiFactorInfoId; + } + + public void setMultiFactorInfoId(@Nullable String setterArg) { + this.multiFactorInfoId = setterArg; + } + + private @Nullable String multiFactorSessionId; + + public @Nullable String getMultiFactorSessionId() { + return multiFactorSessionId; + } + + public void setMultiFactorSessionId(@Nullable String setterArg) { + this.multiFactorSessionId = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonVerifyPhoneNumberRequest() {} + + public static final class Builder { + + private @Nullable String phoneNumber; + + public @NonNull Builder setPhoneNumber(@Nullable String setterArg) { + this.phoneNumber = setterArg; + return this; + } + + private @Nullable Long timeout; + + public @NonNull Builder setTimeout(@NonNull Long setterArg) { + this.timeout = setterArg; + return this; + } + + private @Nullable Long forceResendingToken; + + public @NonNull Builder setForceResendingToken(@Nullable Long setterArg) { + this.forceResendingToken = setterArg; + return this; + } + + private @Nullable String autoRetrievedSmsCodeForTesting; + + public @NonNull Builder setAutoRetrievedSmsCodeForTesting(@Nullable String setterArg) { + this.autoRetrievedSmsCodeForTesting = setterArg; + return this; + } + + private @Nullable String multiFactorInfoId; + + public @NonNull Builder setMultiFactorInfoId(@Nullable String setterArg) { + this.multiFactorInfoId = setterArg; + return this; + } + + private @Nullable String multiFactorSessionId; + + public @NonNull Builder setMultiFactorSessionId(@Nullable String setterArg) { + this.multiFactorSessionId = setterArg; + return this; + } + + public @NonNull PigeonVerifyPhoneNumberRequest build() { + PigeonVerifyPhoneNumberRequest pigeonReturn = new PigeonVerifyPhoneNumberRequest(); + pigeonReturn.setPhoneNumber(phoneNumber); + pigeonReturn.setTimeout(timeout); + pigeonReturn.setForceResendingToken(forceResendingToken); + pigeonReturn.setAutoRetrievedSmsCodeForTesting(autoRetrievedSmsCodeForTesting); + pigeonReturn.setMultiFactorInfoId(multiFactorInfoId); + pigeonReturn.setMultiFactorSessionId(multiFactorSessionId); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(6); + toListResult.add(phoneNumber); + toListResult.add(timeout); + toListResult.add(forceResendingToken); + toListResult.add(autoRetrievedSmsCodeForTesting); + toListResult.add(multiFactorInfoId); + toListResult.add(multiFactorSessionId); + return toListResult; + } + + static @NonNull PigeonVerifyPhoneNumberRequest fromList(@NonNull ArrayList list) { + PigeonVerifyPhoneNumberRequest pigeonResult = new PigeonVerifyPhoneNumberRequest(); + Object phoneNumber = list.get(0); + pigeonResult.setPhoneNumber((String) phoneNumber); + Object timeout = list.get(1); + pigeonResult.setTimeout( + (timeout == null) + ? null + : ((timeout instanceof Integer) ? (Integer) timeout : (Long) timeout)); + Object forceResendingToken = list.get(2); + pigeonResult.setForceResendingToken( + (forceResendingToken == null) + ? null + : ((forceResendingToken instanceof Integer) + ? (Integer) forceResendingToken + : (Long) forceResendingToken)); + Object autoRetrievedSmsCodeForTesting = list.get(3); + pigeonResult.setAutoRetrievedSmsCodeForTesting((String) autoRetrievedSmsCodeForTesting); + Object multiFactorInfoId = list.get(4); + pigeonResult.setMultiFactorInfoId((String) multiFactorInfoId); + Object multiFactorSessionId = list.get(5); + pigeonResult.setMultiFactorSessionId((String) multiFactorSessionId); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonIdTokenResult { + private @Nullable String token; + + public @Nullable String getToken() { + return token; + } + + public void setToken(@Nullable String setterArg) { + this.token = setterArg; + } + + private @Nullable Long expirationTimestamp; + + public @Nullable Long getExpirationTimestamp() { + return expirationTimestamp; + } + + public void setExpirationTimestamp(@Nullable Long setterArg) { + this.expirationTimestamp = setterArg; + } + + private @Nullable Long authTimestamp; + + public @Nullable Long getAuthTimestamp() { + return authTimestamp; + } + + public void setAuthTimestamp(@Nullable Long setterArg) { + this.authTimestamp = setterArg; + } + + private @Nullable Long issuedAtTimestamp; + + public @Nullable Long getIssuedAtTimestamp() { + return issuedAtTimestamp; + } + + public void setIssuedAtTimestamp(@Nullable Long setterArg) { + this.issuedAtTimestamp = setterArg; + } + + private @Nullable String signInProvider; + + public @Nullable String getSignInProvider() { + return signInProvider; + } + + public void setSignInProvider(@Nullable String setterArg) { + this.signInProvider = setterArg; + } + + private @Nullable Map claims; + + public @Nullable Map getClaims() { + return claims; + } + + public void setClaims(@Nullable Map setterArg) { + this.claims = setterArg; + } + + private @Nullable String signInSecondFactor; + + public @Nullable String getSignInSecondFactor() { + return signInSecondFactor; + } + + public void setSignInSecondFactor(@Nullable String setterArg) { + this.signInSecondFactor = setterArg; + } + + public static final class Builder { + + private @Nullable String token; + + public @NonNull Builder setToken(@Nullable String setterArg) { + this.token = setterArg; + return this; + } + + private @Nullable Long expirationTimestamp; + + public @NonNull Builder setExpirationTimestamp(@Nullable Long setterArg) { + this.expirationTimestamp = setterArg; + return this; + } + + private @Nullable Long authTimestamp; + + public @NonNull Builder setAuthTimestamp(@Nullable Long setterArg) { + this.authTimestamp = setterArg; + return this; + } + + private @Nullable Long issuedAtTimestamp; + + public @NonNull Builder setIssuedAtTimestamp(@Nullable Long setterArg) { + this.issuedAtTimestamp = setterArg; + return this; + } + + private @Nullable String signInProvider; + + public @NonNull Builder setSignInProvider(@Nullable String setterArg) { + this.signInProvider = setterArg; + return this; + } + + private @Nullable Map claims; + + public @NonNull Builder setClaims(@Nullable Map setterArg) { + this.claims = setterArg; + return this; + } + + private @Nullable String signInSecondFactor; + + public @NonNull Builder setSignInSecondFactor(@Nullable String setterArg) { + this.signInSecondFactor = setterArg; + return this; + } + + public @NonNull PigeonIdTokenResult build() { + PigeonIdTokenResult pigeonReturn = new PigeonIdTokenResult(); + pigeonReturn.setToken(token); + pigeonReturn.setExpirationTimestamp(expirationTimestamp); + pigeonReturn.setAuthTimestamp(authTimestamp); + pigeonReturn.setIssuedAtTimestamp(issuedAtTimestamp); + pigeonReturn.setSignInProvider(signInProvider); + pigeonReturn.setClaims(claims); + pigeonReturn.setSignInSecondFactor(signInSecondFactor); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(7); + toListResult.add(token); + toListResult.add(expirationTimestamp); + toListResult.add(authTimestamp); + toListResult.add(issuedAtTimestamp); + toListResult.add(signInProvider); + toListResult.add(claims); + toListResult.add(signInSecondFactor); + return toListResult; + } + + static @NonNull PigeonIdTokenResult fromList(@NonNull ArrayList list) { + PigeonIdTokenResult pigeonResult = new PigeonIdTokenResult(); + Object token = list.get(0); + pigeonResult.setToken((String) token); + Object expirationTimestamp = list.get(1); + pigeonResult.setExpirationTimestamp( + (expirationTimestamp == null) + ? null + : ((expirationTimestamp instanceof Integer) + ? (Integer) expirationTimestamp + : (Long) expirationTimestamp)); + Object authTimestamp = list.get(2); + pigeonResult.setAuthTimestamp( + (authTimestamp == null) + ? null + : ((authTimestamp instanceof Integer) + ? (Integer) authTimestamp + : (Long) authTimestamp)); + Object issuedAtTimestamp = list.get(3); + pigeonResult.setIssuedAtTimestamp( + (issuedAtTimestamp == null) + ? null + : ((issuedAtTimestamp instanceof Integer) + ? (Integer) issuedAtTimestamp + : (Long) issuedAtTimestamp)); + Object signInProvider = list.get(4); + pigeonResult.setSignInProvider((String) signInProvider); + Object claims = list.get(5); + pigeonResult.setClaims((Map) claims); + Object signInSecondFactor = list.get(6); + pigeonResult.setSignInSecondFactor((String) signInSecondFactor); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonUserProfile { + private @Nullable String displayName; + + public @Nullable String getDisplayName() { + return displayName; + } + + public void setDisplayName(@Nullable String setterArg) { + this.displayName = setterArg; + } + + private @Nullable String photoUrl; + + public @Nullable String getPhotoUrl() { + return photoUrl; + } + + public void setPhotoUrl(@Nullable String setterArg) { + this.photoUrl = setterArg; + } + + private @NonNull Boolean displayNameChanged; + + public @NonNull Boolean getDisplayNameChanged() { + return displayNameChanged; + } + + public void setDisplayNameChanged(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"displayNameChanged\" is null."); + } + this.displayNameChanged = setterArg; + } + + private @NonNull Boolean photoUrlChanged; + + public @NonNull Boolean getPhotoUrlChanged() { + return photoUrlChanged; + } + + public void setPhotoUrlChanged(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"photoUrlChanged\" is null."); + } + this.photoUrlChanged = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonUserProfile() {} + + public static final class Builder { + + private @Nullable String displayName; + + public @NonNull Builder setDisplayName(@Nullable String setterArg) { + this.displayName = setterArg; + return this; + } + + private @Nullable String photoUrl; + + public @NonNull Builder setPhotoUrl(@Nullable String setterArg) { + this.photoUrl = setterArg; + return this; + } + + private @Nullable Boolean displayNameChanged; + + public @NonNull Builder setDisplayNameChanged(@NonNull Boolean setterArg) { + this.displayNameChanged = setterArg; + return this; + } + + private @Nullable Boolean photoUrlChanged; + + public @NonNull Builder setPhotoUrlChanged(@NonNull Boolean setterArg) { + this.photoUrlChanged = setterArg; + return this; + } + + public @NonNull PigeonUserProfile build() { + PigeonUserProfile pigeonReturn = new PigeonUserProfile(); + pigeonReturn.setDisplayName(displayName); + pigeonReturn.setPhotoUrl(photoUrl); + pigeonReturn.setDisplayNameChanged(displayNameChanged); + pigeonReturn.setPhotoUrlChanged(photoUrlChanged); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(4); + toListResult.add(displayName); + toListResult.add(photoUrl); + toListResult.add(displayNameChanged); + toListResult.add(photoUrlChanged); + return toListResult; + } + + static @NonNull PigeonUserProfile fromList(@NonNull ArrayList list) { + PigeonUserProfile pigeonResult = new PigeonUserProfile(); + Object displayName = list.get(0); + pigeonResult.setDisplayName((String) displayName); + Object photoUrl = list.get(1); + pigeonResult.setPhotoUrl((String) photoUrl); + Object displayNameChanged = list.get(2); + pigeonResult.setDisplayNameChanged((Boolean) displayNameChanged); + Object photoUrlChanged = list.get(3); + pigeonResult.setPhotoUrlChanged((Boolean) photoUrlChanged); + return pigeonResult; + } + } + + public interface Result { + @SuppressWarnings("UnknownNullness") + void success(T result); + + void error(@NonNull Throwable error); + } + + private static class FirebaseAuthHostApiCodec extends StandardMessageCodec { + public static final FirebaseAuthHostApiCodec INSTANCE = new FirebaseAuthHostApiCodec(); + + private FirebaseAuthHostApiCodec() {} + + @Override + protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { + switch (type) { + case (byte) 128: + return PigeonActionCodeInfo.fromList((ArrayList) readValue(buffer)); + case (byte) 129: + return PigeonActionCodeInfoData.fromList((ArrayList) readValue(buffer)); + case (byte) 130: + return PigeonActionCodeSettings.fromList((ArrayList) readValue(buffer)); + case (byte) 131: + return PigeonAdditionalUserInfo.fromList((ArrayList) readValue(buffer)); + case (byte) 132: + return PigeonAuthCredential.fromList((ArrayList) readValue(buffer)); + case (byte) 133: + return PigeonFirebaseApp.fromList((ArrayList) readValue(buffer)); + case (byte) 134: + return PigeonFirebaseAuthSettings.fromList((ArrayList) readValue(buffer)); + case (byte) 135: + return PigeonIdTokenResult.fromList((ArrayList) readValue(buffer)); + case (byte) 136: + return PigeonMultiFactorInfo.fromList((ArrayList) readValue(buffer)); + case (byte) 137: + return PigeonMultiFactorSession.fromList((ArrayList) readValue(buffer)); + case (byte) 138: + return PigeonPhoneMultiFactorAssertion.fromList((ArrayList) readValue(buffer)); + case (byte) 139: + return PigeonSignInProvider.fromList((ArrayList) readValue(buffer)); + case (byte) 140: + return PigeonUserCredential.fromList((ArrayList) readValue(buffer)); + case (byte) 141: + return PigeonUserDetails.fromList((ArrayList) readValue(buffer)); + case (byte) 142: + return PigeonUserInfo.fromList((ArrayList) readValue(buffer)); + case (byte) 143: + return PigeonUserProfile.fromList((ArrayList) readValue(buffer)); + case (byte) 144: + return PigeonVerifyPhoneNumberRequest.fromList((ArrayList) readValue(buffer)); + default: + return super.readValueOfType(type, buffer); + } + } + + @Override + protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { + if (value instanceof PigeonActionCodeInfo) { + stream.write(128); + writeValue(stream, ((PigeonActionCodeInfo) value).toList()); + } else if (value instanceof PigeonActionCodeInfoData) { + stream.write(129); + writeValue(stream, ((PigeonActionCodeInfoData) value).toList()); + } else if (value instanceof PigeonActionCodeSettings) { + stream.write(130); + writeValue(stream, ((PigeonActionCodeSettings) value).toList()); + } else if (value instanceof PigeonAdditionalUserInfo) { + stream.write(131); + writeValue(stream, ((PigeonAdditionalUserInfo) value).toList()); + } else if (value instanceof PigeonAuthCredential) { + stream.write(132); + writeValue(stream, ((PigeonAuthCredential) value).toList()); + } else if (value instanceof PigeonFirebaseApp) { + stream.write(133); + writeValue(stream, ((PigeonFirebaseApp) value).toList()); + } else if (value instanceof PigeonFirebaseAuthSettings) { + stream.write(134); + writeValue(stream, ((PigeonFirebaseAuthSettings) value).toList()); + } else if (value instanceof PigeonIdTokenResult) { + stream.write(135); + writeValue(stream, ((PigeonIdTokenResult) value).toList()); + } else if (value instanceof PigeonMultiFactorInfo) { + stream.write(136); + writeValue(stream, ((PigeonMultiFactorInfo) value).toList()); + } else if (value instanceof PigeonMultiFactorSession) { + stream.write(137); + writeValue(stream, ((PigeonMultiFactorSession) value).toList()); + } else if (value instanceof PigeonPhoneMultiFactorAssertion) { + stream.write(138); + writeValue(stream, ((PigeonPhoneMultiFactorAssertion) value).toList()); + } else if (value instanceof PigeonSignInProvider) { + stream.write(139); + writeValue(stream, ((PigeonSignInProvider) value).toList()); + } else if (value instanceof PigeonUserCredential) { + stream.write(140); + writeValue(stream, ((PigeonUserCredential) value).toList()); + } else if (value instanceof PigeonUserDetails) { + stream.write(141); + writeValue(stream, ((PigeonUserDetails) value).toList()); + } else if (value instanceof PigeonUserInfo) { + stream.write(142); + writeValue(stream, ((PigeonUserInfo) value).toList()); + } else if (value instanceof PigeonUserProfile) { + stream.write(143); + writeValue(stream, ((PigeonUserProfile) value).toList()); + } else if (value instanceof PigeonVerifyPhoneNumberRequest) { + stream.write(144); + writeValue(stream, ((PigeonVerifyPhoneNumberRequest) value).toList()); + } else { + super.writeValue(stream, value); + } + } + } + + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface FirebaseAuthHostApi { + + void registerIdTokenListener(@NonNull PigeonFirebaseApp app, @NonNull Result result); + + void registerAuthStateListener(@NonNull PigeonFirebaseApp app, @NonNull Result result); + + void useEmulator( + @NonNull PigeonFirebaseApp app, + @NonNull String host, + @NonNull Long port, + @NonNull Result result); + + void applyActionCode( + @NonNull PigeonFirebaseApp app, @NonNull String code, @NonNull Result result); + + void checkActionCode( + @NonNull PigeonFirebaseApp app, + @NonNull String code, + @NonNull Result result); + + void confirmPasswordReset( + @NonNull PigeonFirebaseApp app, + @NonNull String code, + @NonNull String newPassword, + @NonNull Result result); + + void createUserWithEmailAndPassword( + @NonNull PigeonFirebaseApp app, + @NonNull String email, + @NonNull String password, + @NonNull Result result); + + void signInAnonymously( + @NonNull PigeonFirebaseApp app, @NonNull Result result); + + void signInWithCredential( + @NonNull PigeonFirebaseApp app, + @NonNull Map input, + @NonNull Result result); + + void signInWithCustomToken( + @NonNull PigeonFirebaseApp app, + @NonNull String token, + @NonNull Result result); + + void signInWithEmailAndPassword( + @NonNull PigeonFirebaseApp app, + @NonNull String email, + @NonNull String password, + @NonNull Result result); + + void signInWithEmailLink( + @NonNull PigeonFirebaseApp app, + @NonNull String email, + @NonNull String emailLink, + @NonNull Result result); + + void signInWithProvider( + @NonNull PigeonFirebaseApp app, + @NonNull PigeonSignInProvider signInProvider, + @NonNull Result result); + + void signOut(@NonNull PigeonFirebaseApp app, @NonNull Result result); + + void fetchSignInMethodsForEmail( + @NonNull PigeonFirebaseApp app, + @NonNull String email, + @NonNull Result> result); + + void sendPasswordResetEmail( + @NonNull PigeonFirebaseApp app, + @NonNull String email, + @Nullable PigeonActionCodeSettings actionCodeSettings, + @NonNull Result result); + + void sendSignInLinkToEmail( + @NonNull PigeonFirebaseApp app, + @NonNull String email, + @NonNull PigeonActionCodeSettings actionCodeSettings, + @NonNull Result result); + + void setLanguageCode( + @NonNull PigeonFirebaseApp app, + @Nullable String languageCode, + @NonNull Result result); + + void setSettings( + @NonNull PigeonFirebaseApp app, + @NonNull PigeonFirebaseAuthSettings settings, + @NonNull Result result); + + void verifyPasswordResetCode( + @NonNull PigeonFirebaseApp app, @NonNull String code, @NonNull Result result); + + void verifyPhoneNumber( + @NonNull PigeonFirebaseApp app, + @NonNull PigeonVerifyPhoneNumberRequest request, + @NonNull Result result); + + /** The codec used by FirebaseAuthHostApi. */ + static @NonNull MessageCodec getCodec() { + return FirebaseAuthHostApiCodec.INSTANCE; + } + /** + * Sets up an instance of `FirebaseAuthHostApi` to handle messages through the + * `binaryMessenger`. + */ + static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable FirebaseAuthHostApi api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.registerIdTokenListener", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + Result resultCallback = + new Result() { + public void success(String result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.registerIdTokenListener(appArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.registerAuthStateListener", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + Result resultCallback = + new Result() { + public void success(String result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.registerAuthStateListener(appArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.FirebaseAuthHostApi.useEmulator", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String hostArg = (String) args.get(1); + Number portArg = (Number) args.get(2); + Result resultCallback = + new Result() { + public void success(Void result) { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.useEmulator( + appArg, + hostArg, + (portArg == null) ? null : portArg.longValue(), + resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.applyActionCode", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String codeArg = (String) args.get(1); + Result resultCallback = + new Result() { + public void success(Void result) { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.applyActionCode(appArg, codeArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.checkActionCode", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String codeArg = (String) args.get(1); + Result resultCallback = + new Result() { + public void success(PigeonActionCodeInfo result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.checkActionCode(appArg, codeArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.confirmPasswordReset", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String codeArg = (String) args.get(1); + String newPasswordArg = (String) args.get(2); + Result resultCallback = + new Result() { + public void success(Void result) { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.confirmPasswordReset(appArg, codeArg, newPasswordArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.createUserWithEmailAndPassword", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String emailArg = (String) args.get(1); + String passwordArg = (String) args.get(2); + Result resultCallback = + new Result() { + public void success(PigeonUserCredential result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.createUserWithEmailAndPassword(appArg, emailArg, passwordArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.signInAnonymously", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + Result resultCallback = + new Result() { + public void success(PigeonUserCredential result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.signInAnonymously(appArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.signInWithCredential", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + Map inputArg = (Map) args.get(1); + Result resultCallback = + new Result() { + public void success(PigeonUserCredential result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.signInWithCredential(appArg, inputArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.signInWithCustomToken", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String tokenArg = (String) args.get(1); + Result resultCallback = + new Result() { + public void success(PigeonUserCredential result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.signInWithCustomToken(appArg, tokenArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailAndPassword", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String emailArg = (String) args.get(1); + String passwordArg = (String) args.get(2); + Result resultCallback = + new Result() { + public void success(PigeonUserCredential result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.signInWithEmailAndPassword(appArg, emailArg, passwordArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailLink", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String emailArg = (String) args.get(1); + String emailLinkArg = (String) args.get(2); + Result resultCallback = + new Result() { + public void success(PigeonUserCredential result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.signInWithEmailLink(appArg, emailArg, emailLinkArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.signInWithProvider", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + PigeonSignInProvider signInProviderArg = (PigeonSignInProvider) args.get(1); + Result resultCallback = + new Result() { + public void success(PigeonUserCredential result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.signInWithProvider(appArg, signInProviderArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.FirebaseAuthHostApi.signOut", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + Result resultCallback = + new Result() { + public void success(Void result) { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.signOut(appArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.fetchSignInMethodsForEmail", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String emailArg = (String) args.get(1); + Result> resultCallback = + new Result>() { + public void success(List result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.fetchSignInMethodsForEmail(appArg, emailArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.sendPasswordResetEmail", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String emailArg = (String) args.get(1); + PigeonActionCodeSettings actionCodeSettingsArg = + (PigeonActionCodeSettings) args.get(2); + Result resultCallback = + new Result() { + public void success(Void result) { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.sendPasswordResetEmail(appArg, emailArg, actionCodeSettingsArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.sendSignInLinkToEmail", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String emailArg = (String) args.get(1); + PigeonActionCodeSettings actionCodeSettingsArg = + (PigeonActionCodeSettings) args.get(2); + Result resultCallback = + new Result() { + public void success(Void result) { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.sendSignInLinkToEmail(appArg, emailArg, actionCodeSettingsArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.setLanguageCode", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String languageCodeArg = (String) args.get(1); + Result resultCallback = + new Result() { + public void success(String result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.setLanguageCode(appArg, languageCodeArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.FirebaseAuthHostApi.setSettings", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + PigeonFirebaseAuthSettings settingsArg = (PigeonFirebaseAuthSettings) args.get(1); + Result resultCallback = + new Result() { + public void success(Void result) { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.setSettings(appArg, settingsArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.verifyPasswordResetCode", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String codeArg = (String) args.get(1); + Result resultCallback = + new Result() { + public void success(String result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.verifyPasswordResetCode(appArg, codeArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthHostApi.verifyPhoneNumber", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + PigeonVerifyPhoneNumberRequest requestArg = + (PigeonVerifyPhoneNumberRequest) args.get(1); + Result resultCallback = + new Result() { + public void success(String result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.verifyPhoneNumber(appArg, requestArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } + + private static class FirebaseAuthUserHostApiCodec extends StandardMessageCodec { + public static final FirebaseAuthUserHostApiCodec INSTANCE = new FirebaseAuthUserHostApiCodec(); + + private FirebaseAuthUserHostApiCodec() {} + + @Override + protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { + switch (type) { + case (byte) 128: + return PigeonActionCodeInfo.fromList((ArrayList) readValue(buffer)); + case (byte) 129: + return PigeonActionCodeInfoData.fromList((ArrayList) readValue(buffer)); + case (byte) 130: + return PigeonActionCodeSettings.fromList((ArrayList) readValue(buffer)); + case (byte) 131: + return PigeonAdditionalUserInfo.fromList((ArrayList) readValue(buffer)); + case (byte) 132: + return PigeonAuthCredential.fromList((ArrayList) readValue(buffer)); + case (byte) 133: + return PigeonFirebaseApp.fromList((ArrayList) readValue(buffer)); + case (byte) 134: + return PigeonFirebaseAuthSettings.fromList((ArrayList) readValue(buffer)); + case (byte) 135: + return PigeonIdTokenResult.fromList((ArrayList) readValue(buffer)); + case (byte) 136: + return PigeonMultiFactorInfo.fromList((ArrayList) readValue(buffer)); + case (byte) 137: + return PigeonMultiFactorSession.fromList((ArrayList) readValue(buffer)); + case (byte) 138: + return PigeonPhoneMultiFactorAssertion.fromList((ArrayList) readValue(buffer)); + case (byte) 139: + return PigeonSignInProvider.fromList((ArrayList) readValue(buffer)); + case (byte) 140: + return PigeonUserCredential.fromList((ArrayList) readValue(buffer)); + case (byte) 141: + return PigeonUserDetails.fromList((ArrayList) readValue(buffer)); + case (byte) 142: + return PigeonUserInfo.fromList((ArrayList) readValue(buffer)); + case (byte) 143: + return PigeonUserProfile.fromList((ArrayList) readValue(buffer)); + case (byte) 144: + return PigeonVerifyPhoneNumberRequest.fromList((ArrayList) readValue(buffer)); + default: + return super.readValueOfType(type, buffer); + } + } + + @Override + protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { + if (value instanceof PigeonActionCodeInfo) { + stream.write(128); + writeValue(stream, ((PigeonActionCodeInfo) value).toList()); + } else if (value instanceof PigeonActionCodeInfoData) { + stream.write(129); + writeValue(stream, ((PigeonActionCodeInfoData) value).toList()); + } else if (value instanceof PigeonActionCodeSettings) { + stream.write(130); + writeValue(stream, ((PigeonActionCodeSettings) value).toList()); + } else if (value instanceof PigeonAdditionalUserInfo) { + stream.write(131); + writeValue(stream, ((PigeonAdditionalUserInfo) value).toList()); + } else if (value instanceof PigeonAuthCredential) { + stream.write(132); + writeValue(stream, ((PigeonAuthCredential) value).toList()); + } else if (value instanceof PigeonFirebaseApp) { + stream.write(133); + writeValue(stream, ((PigeonFirebaseApp) value).toList()); + } else if (value instanceof PigeonFirebaseAuthSettings) { + stream.write(134); + writeValue(stream, ((PigeonFirebaseAuthSettings) value).toList()); + } else if (value instanceof PigeonIdTokenResult) { + stream.write(135); + writeValue(stream, ((PigeonIdTokenResult) value).toList()); + } else if (value instanceof PigeonMultiFactorInfo) { + stream.write(136); + writeValue(stream, ((PigeonMultiFactorInfo) value).toList()); + } else if (value instanceof PigeonMultiFactorSession) { + stream.write(137); + writeValue(stream, ((PigeonMultiFactorSession) value).toList()); + } else if (value instanceof PigeonPhoneMultiFactorAssertion) { + stream.write(138); + writeValue(stream, ((PigeonPhoneMultiFactorAssertion) value).toList()); + } else if (value instanceof PigeonSignInProvider) { + stream.write(139); + writeValue(stream, ((PigeonSignInProvider) value).toList()); + } else if (value instanceof PigeonUserCredential) { + stream.write(140); + writeValue(stream, ((PigeonUserCredential) value).toList()); + } else if (value instanceof PigeonUserDetails) { + stream.write(141); + writeValue(stream, ((PigeonUserDetails) value).toList()); + } else if (value instanceof PigeonUserInfo) { + stream.write(142); + writeValue(stream, ((PigeonUserInfo) value).toList()); + } else if (value instanceof PigeonUserProfile) { + stream.write(143); + writeValue(stream, ((PigeonUserProfile) value).toList()); + } else if (value instanceof PigeonVerifyPhoneNumberRequest) { + stream.write(144); + writeValue(stream, ((PigeonVerifyPhoneNumberRequest) value).toList()); + } else { + super.writeValue(stream, value); + } + } + } + + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface FirebaseAuthUserHostApi { + + void delete(@NonNull PigeonFirebaseApp app, @NonNull Result result); + + void getIdToken( + @NonNull PigeonFirebaseApp app, + @NonNull Boolean forceRefresh, + @NonNull Result result); + + void linkWithCredential( + @NonNull PigeonFirebaseApp app, + @NonNull Map input, + @NonNull Result result); + + void linkWithProvider( + @NonNull PigeonFirebaseApp app, + @NonNull PigeonSignInProvider signInProvider, + @NonNull Result result); + + void reauthenticateWithCredential( + @NonNull PigeonFirebaseApp app, + @NonNull Map input, + @NonNull Result result); + + void reauthenticateWithProvider( + @NonNull PigeonFirebaseApp app, + @NonNull PigeonSignInProvider signInProvider, + @NonNull Result result); + + void reload(@NonNull PigeonFirebaseApp app, @NonNull Result result); + + void sendEmailVerification( + @NonNull PigeonFirebaseApp app, + @Nullable PigeonActionCodeSettings actionCodeSettings, + @NonNull Result result); + + void unlink( + @NonNull PigeonFirebaseApp app, + @NonNull String providerId, + @NonNull Result result); + + void updateEmail( + @NonNull PigeonFirebaseApp app, + @NonNull String newEmail, + @NonNull Result result); + + void updatePassword( + @NonNull PigeonFirebaseApp app, + @NonNull String newPassword, + @NonNull Result result); + + void updatePhoneNumber( + @NonNull PigeonFirebaseApp app, + @NonNull Map input, + @NonNull Result result); + + void updateProfile( + @NonNull PigeonFirebaseApp app, + @NonNull PigeonUserProfile profile, + @NonNull Result result); + + void verifyBeforeUpdateEmail( + @NonNull PigeonFirebaseApp app, + @NonNull String newEmail, + @Nullable PigeonActionCodeSettings actionCodeSettings, + @NonNull Result result); + + /** The codec used by FirebaseAuthUserHostApi. */ + static @NonNull MessageCodec getCodec() { + return FirebaseAuthUserHostApiCodec.INSTANCE; + } + /** + * Sets up an instance of `FirebaseAuthUserHostApi` to handle messages through the + * `binaryMessenger`. + */ + static void setup( + @NonNull BinaryMessenger binaryMessenger, @Nullable FirebaseAuthUserHostApi api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.FirebaseAuthUserHostApi.delete", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + Result resultCallback = + new Result() { + public void success(Void result) { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.delete(appArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthUserHostApi.getIdToken", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + Boolean forceRefreshArg = (Boolean) args.get(1); + Result resultCallback = + new Result() { + public void success(PigeonIdTokenResult result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.getIdToken(appArg, forceRefreshArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthUserHostApi.linkWithCredential", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + Map inputArg = (Map) args.get(1); + Result resultCallback = + new Result() { + public void success(PigeonUserCredential result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.linkWithCredential(appArg, inputArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthUserHostApi.linkWithProvider", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + PigeonSignInProvider signInProviderArg = (PigeonSignInProvider) args.get(1); + Result resultCallback = + new Result() { + public void success(PigeonUserCredential result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.linkWithProvider(appArg, signInProviderArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthUserHostApi.reauthenticateWithCredential", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + Map inputArg = (Map) args.get(1); + Result resultCallback = + new Result() { + public void success(PigeonUserCredential result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.reauthenticateWithCredential(appArg, inputArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthUserHostApi.reauthenticateWithProvider", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + PigeonSignInProvider signInProviderArg = (PigeonSignInProvider) args.get(1); + Result resultCallback = + new Result() { + public void success(PigeonUserCredential result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.reauthenticateWithProvider(appArg, signInProviderArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.FirebaseAuthUserHostApi.reload", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + Result resultCallback = + new Result() { + public void success(PigeonUserDetails result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.reload(appArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthUserHostApi.sendEmailVerification", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + PigeonActionCodeSettings actionCodeSettingsArg = + (PigeonActionCodeSettings) args.get(1); + Result resultCallback = + new Result() { + public void success(Void result) { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.sendEmailVerification(appArg, actionCodeSettingsArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.FirebaseAuthUserHostApi.unlink", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String providerIdArg = (String) args.get(1); + Result resultCallback = + new Result() { + public void success(PigeonUserCredential result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.unlink(appArg, providerIdArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthUserHostApi.updateEmail", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String newEmailArg = (String) args.get(1); + Result resultCallback = + new Result() { + public void success(PigeonUserDetails result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.updateEmail(appArg, newEmailArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthUserHostApi.updatePassword", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String newPasswordArg = (String) args.get(1); + Result resultCallback = + new Result() { + public void success(PigeonUserDetails result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.updatePassword(appArg, newPasswordArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthUserHostApi.updatePhoneNumber", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + Map inputArg = (Map) args.get(1); + Result resultCallback = + new Result() { + public void success(PigeonUserDetails result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.updatePhoneNumber(appArg, inputArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthUserHostApi.updateProfile", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + PigeonUserProfile profileArg = (PigeonUserProfile) args.get(1); + Result resultCallback = + new Result() { + public void success(PigeonUserDetails result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.updateProfile(appArg, profileArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.FirebaseAuthUserHostApi.verifyBeforeUpdateEmail", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String newEmailArg = (String) args.get(1); + PigeonActionCodeSettings actionCodeSettingsArg = + (PigeonActionCodeSettings) args.get(2); + Result resultCallback = + new Result() { + public void success(Void result) { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.verifyBeforeUpdateEmail( + appArg, newEmailArg, actionCodeSettingsArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } + + private static class MultiFactorUserHostApiCodec extends StandardMessageCodec { + public static final MultiFactorUserHostApiCodec INSTANCE = new MultiFactorUserHostApiCodec(); + + private MultiFactorUserHostApiCodec() {} + + @Override + protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { + switch (type) { + case (byte) 128: + return PigeonFirebaseApp.fromList((ArrayList) readValue(buffer)); + case (byte) 129: + return PigeonMultiFactorInfo.fromList((ArrayList) readValue(buffer)); + case (byte) 130: + return PigeonMultiFactorSession.fromList((ArrayList) readValue(buffer)); + case (byte) 131: + return PigeonPhoneMultiFactorAssertion.fromList((ArrayList) readValue(buffer)); + default: + return super.readValueOfType(type, buffer); + } + } + + @Override + protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { + if (value instanceof PigeonFirebaseApp) { + stream.write(128); + writeValue(stream, ((PigeonFirebaseApp) value).toList()); + } else if (value instanceof PigeonMultiFactorInfo) { + stream.write(129); + writeValue(stream, ((PigeonMultiFactorInfo) value).toList()); + } else if (value instanceof PigeonMultiFactorSession) { + stream.write(130); + writeValue(stream, ((PigeonMultiFactorSession) value).toList()); + } else if (value instanceof PigeonPhoneMultiFactorAssertion) { + stream.write(131); + writeValue(stream, ((PigeonPhoneMultiFactorAssertion) value).toList()); + } else { + super.writeValue(stream, value); + } + } + } + + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface MultiFactorUserHostApi { + + void enrollPhone( + @NonNull PigeonFirebaseApp app, + @NonNull PigeonPhoneMultiFactorAssertion assertion, + @Nullable String displayName, + @NonNull Result result); + + void getSession( + @NonNull PigeonFirebaseApp app, @NonNull Result result); + + void unenroll( + @NonNull PigeonFirebaseApp app, @NonNull String factorUid, @NonNull Result result); + + void getEnrolledFactors( + @NonNull PigeonFirebaseApp app, @NonNull Result> result); + + /** The codec used by MultiFactorUserHostApi. */ + static @NonNull MessageCodec getCodec() { + return MultiFactorUserHostApiCodec.INSTANCE; + } + /** + * Sets up an instance of `MultiFactorUserHostApi` to handle messages through the + * `binaryMessenger`. + */ + static void setup( + @NonNull BinaryMessenger binaryMessenger, @Nullable MultiFactorUserHostApi api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.MultiFactorUserHostApi.enrollPhone", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + PigeonPhoneMultiFactorAssertion assertionArg = + (PigeonPhoneMultiFactorAssertion) args.get(1); + String displayNameArg = (String) args.get(2); + Result resultCallback = + new Result() { + public void success(Void result) { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.enrollPhone(appArg, assertionArg, displayNameArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.MultiFactorUserHostApi.getSession", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + Result resultCallback = + new Result() { + public void success(PigeonMultiFactorSession result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.getSession(appArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.MultiFactorUserHostApi.unenroll", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + String factorUidArg = (String) args.get(1); + Result resultCallback = + new Result() { + public void success(Void result) { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.unenroll(appArg, factorUidArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.MultiFactorUserHostApi.getEnrolledFactors", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonFirebaseApp appArg = (PigeonFirebaseApp) args.get(0); + Result> resultCallback = + new Result>() { + public void success(List result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.getEnrolledFactors(appArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } + + private static class MultiFactoResolverHostApiCodec extends StandardMessageCodec { + public static final MultiFactoResolverHostApiCodec INSTANCE = + new MultiFactoResolverHostApiCodec(); + + private MultiFactoResolverHostApiCodec() {} + + @Override + protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { + switch (type) { + case (byte) 128: + return PigeonAdditionalUserInfo.fromList((ArrayList) readValue(buffer)); + case (byte) 129: + return PigeonAuthCredential.fromList((ArrayList) readValue(buffer)); + case (byte) 130: + return PigeonPhoneMultiFactorAssertion.fromList((ArrayList) readValue(buffer)); + case (byte) 131: + return PigeonUserCredential.fromList((ArrayList) readValue(buffer)); + case (byte) 132: + return PigeonUserDetails.fromList((ArrayList) readValue(buffer)); + case (byte) 133: + return PigeonUserInfo.fromList((ArrayList) readValue(buffer)); + default: + return super.readValueOfType(type, buffer); + } + } + + @Override + protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { + if (value instanceof PigeonAdditionalUserInfo) { + stream.write(128); + writeValue(stream, ((PigeonAdditionalUserInfo) value).toList()); + } else if (value instanceof PigeonAuthCredential) { + stream.write(129); + writeValue(stream, ((PigeonAuthCredential) value).toList()); + } else if (value instanceof PigeonPhoneMultiFactorAssertion) { + stream.write(130); + writeValue(stream, ((PigeonPhoneMultiFactorAssertion) value).toList()); + } else if (value instanceof PigeonUserCredential) { + stream.write(131); + writeValue(stream, ((PigeonUserCredential) value).toList()); + } else if (value instanceof PigeonUserDetails) { + stream.write(132); + writeValue(stream, ((PigeonUserDetails) value).toList()); + } else if (value instanceof PigeonUserInfo) { + stream.write(133); + writeValue(stream, ((PigeonUserInfo) value).toList()); + } else { + super.writeValue(stream, value); + } + } + } + + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface MultiFactoResolverHostApi { + + void resolveSignIn( + @NonNull String resolverId, + @NonNull PigeonPhoneMultiFactorAssertion assertion, + @NonNull Result result); + + /** The codec used by MultiFactoResolverHostApi. */ + static @NonNull MessageCodec getCodec() { + return MultiFactoResolverHostApiCodec.INSTANCE; + } + /** + * Sets up an instance of `MultiFactoResolverHostApi` to handle messages through the + * `binaryMessenger`. + */ + static void setup( + @NonNull BinaryMessenger binaryMessenger, @Nullable MultiFactoResolverHostApi api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.MultiFactoResolverHostApi.resolveSignIn", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + String resolverIdArg = (String) args.get(0); + PigeonPhoneMultiFactorAssertion assertionArg = + (PigeonPhoneMultiFactorAssertion) args.get(1); + Result resultCallback = + new Result() { + public void success(PigeonUserCredential result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.resolveSignIn(resolverIdArg, assertionArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } + + private static class GenerateInterfacesCodec extends StandardMessageCodec { + public static final GenerateInterfacesCodec INSTANCE = new GenerateInterfacesCodec(); + + private GenerateInterfacesCodec() {} + + @Override + protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { + switch (type) { + case (byte) 128: + return PigeonMultiFactorInfo.fromList((ArrayList) readValue(buffer)); + default: + return super.readValueOfType(type, buffer); + } + } + + @Override + protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { + if (value instanceof PigeonMultiFactorInfo) { + stream.write(128); + writeValue(stream, ((PigeonMultiFactorInfo) value).toList()); + } else { + super.writeValue(stream, value); + } + } + } + + /** + * Only used to generate the object interface that are use outside of the Pigeon interface + * + *

Generated interface from Pigeon that represents a handler of messages from Flutter. + */ + public interface GenerateInterfaces { + + void generateInterfaces(@NonNull PigeonMultiFactorInfo info); + + /** The codec used by GenerateInterfaces. */ + static @NonNull MessageCodec getCodec() { + return GenerateInterfacesCodec.INSTANCE; + } + /** + * Sets up an instance of `GenerateInterfaces` to handle messages through the `binaryMessenger`. + */ + static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable GenerateInterfaces api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.GenerateInterfaces.generateInterfaces", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + PigeonMultiFactorInfo infoArg = (PigeonMultiFactorInfo) args.get(0); + try { + api.generateInterfaces(infoArg); + wrapped.add(0, null); + } catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + } } } diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/IdTokenChannelStreamHandler.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/IdTokenChannelStreamHandler.java index ed78d539a2e2..eec91e72ec66 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/IdTokenChannelStreamHandler.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/IdTokenChannelStreamHandler.java @@ -6,8 +6,6 @@ package io.flutter.plugins.firebase.auth; -import static io.flutter.plugins.firebase.auth.FlutterFirebaseAuthPlugin.parseFirebaseUser; - import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseAuth.IdTokenListener; import com.google.firebase.auth.FirebaseUser; @@ -45,7 +43,7 @@ public void onListen(Object arguments, EventSink events) { if (user == null) { event.put(Constants.USER, null); } else { - event.put(Constants.USER, parseFirebaseUser(user)); + event.put(Constants.USER, PigeonParser.parseFirebaseUser(user).toList()); } events.success(event); diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PhoneNumberVerificationStreamHandler.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PhoneNumberVerificationStreamHandler.java index 0ebdac0dd95a..0195075cbfaf 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PhoneNumberVerificationStreamHandler.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PhoneNumberVerificationStreamHandler.java @@ -21,7 +21,6 @@ import io.flutter.plugin.common.EventChannel.StreamHandler; import java.util.HashMap; import java.util.Map; -import java.util.Objects; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; @@ -49,7 +48,8 @@ interface OnCredentialsListener { public PhoneNumberVerificationStreamHandler( Activity activity, - Map arguments, + @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseApp app, + @NonNull GeneratedAndroidFirebaseAuth.PigeonVerifyPhoneNumberRequest request, @Nullable MultiFactorSession multiFactorSession, @Nullable PhoneMultiFactorInfo multiFactorInfo, OnCredentialsListener onCredentialsListener) { @@ -57,17 +57,16 @@ public PhoneNumberVerificationStreamHandler( this.multiFactorSession = multiFactorSession; this.multiFactorInfo = multiFactorInfo; - firebaseAuth = FlutterFirebaseAuthPlugin.getAuth(arguments); - phoneNumber = (String) arguments.get(Constants.PHONE_NUMBER); - timeout = (int) Objects.requireNonNull(arguments.get(Constants.TIMEOUT)); + firebaseAuth = FlutterFirebaseAuthPlugin.getAuthFromPigeon(app); + phoneNumber = request.getPhoneNumber(); + timeout = Math.toIntExact(request.getTimeout()); - if (arguments.containsKey(Constants.AUTO_RETRIEVED_SMS_CODE_FOR_TESTING)) { - autoRetrievedSmsCodeForTesting = - (String) arguments.get(Constants.AUTO_RETRIEVED_SMS_CODE_FOR_TESTING); + if (request.getAutoRetrievedSmsCodeForTesting() != null) { + autoRetrievedSmsCodeForTesting = request.getAutoRetrievedSmsCodeForTesting(); } - if (arguments.containsKey(Constants.FORCE_RESENDING_TOKEN)) { - forceResendingToken = (Integer) arguments.get(Constants.FORCE_RESENDING_TOKEN); + if (request.getForceResendingToken() != null) { + forceResendingToken = Math.toIntExact(request.getForceResendingToken()); } this.onCredentialsListener = onCredentialsListener; @@ -100,11 +99,15 @@ public void onVerificationCompleted(@NonNull PhoneAuthCredential phoneAuthCreden @Override public void onVerificationFailed(@NonNull FirebaseException e) { - Map error = new HashMap<>(); - error.put("message", e.getLocalizedMessage()); - error.put("details", FlutterFirebaseAuthPlugin.getExceptionDetails(e)); - Map event = new HashMap<>(); + Map error = new HashMap<>(); + GeneratedAndroidFirebaseAuth.FlutterError flutterError = + FlutterFirebaseAuthPluginException.parserExceptionToFlutter(e); + error.put( + "code", + flutterError.code.replaceAll("ERROR_", "").toLowerCase().replaceAll("_", "-")); + error.put("message", flutterError.getMessage()); + error.put("details", flutterError.details); event.put("error", error); event.put(Constants.NAME, "Auth#phoneVerificationFailed"); diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PigeonParser.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PigeonParser.java new file mode 100644 index 000000000000..ddcfd8729e68 --- /dev/null +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PigeonParser.java @@ -0,0 +1,360 @@ +/* + * Copyright 2023, the Chromium project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +package io.flutter.plugins.firebase.auth; + +import android.net.Uri; +import androidx.annotation.NonNull; +import com.google.firebase.auth.ActionCodeEmailInfo; +import com.google.firebase.auth.ActionCodeInfo; +import com.google.firebase.auth.ActionCodeResult; +import com.google.firebase.auth.ActionCodeSettings; +import com.google.firebase.auth.AdditionalUserInfo; +import com.google.firebase.auth.AuthCredential; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.EmailAuthProvider; +import com.google.firebase.auth.FacebookAuthProvider; +import com.google.firebase.auth.FirebaseAuthProvider; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.auth.FirebaseUserMetadata; +import com.google.firebase.auth.GetTokenResult; +import com.google.firebase.auth.GithubAuthProvider; +import com.google.firebase.auth.GoogleAuthProvider; +import com.google.firebase.auth.MultiFactorInfo; +import com.google.firebase.auth.OAuthCredential; +import com.google.firebase.auth.OAuthProvider; +import com.google.firebase.auth.PhoneAuthProvider; +import com.google.firebase.auth.PhoneMultiFactorInfo; +import com.google.firebase.auth.TwitterAuthProvider; +import com.google.firebase.auth.UserInfo; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +public class PigeonParser { + static GeneratedAndroidFirebaseAuth.PigeonUserCredential parseAuthResult( + @NonNull AuthResult authResult) { + GeneratedAndroidFirebaseAuth.PigeonUserCredential.Builder builder = + new GeneratedAndroidFirebaseAuth.PigeonUserCredential.Builder(); + + builder.setAdditionalUserInfo(parseAdditionalUserInfo(authResult.getAdditionalUserInfo())); + builder.setCredential(parseAuthCredential(authResult.getCredential())); + builder.setUser(parseFirebaseUser(authResult.getUser())); + + return builder.build(); + } + + private static GeneratedAndroidFirebaseAuth.PigeonAdditionalUserInfo parseAdditionalUserInfo( + AdditionalUserInfo additionalUserInfo) { + if (additionalUserInfo == null) { + return null; + } + + GeneratedAndroidFirebaseAuth.PigeonAdditionalUserInfo.Builder builder = + new GeneratedAndroidFirebaseAuth.PigeonAdditionalUserInfo.Builder(); + + builder.setIsNewUser(additionalUserInfo.isNewUser()); + builder.setProfile(additionalUserInfo.getProfile()); + builder.setProviderId(additionalUserInfo.getProviderId()); + builder.setUsername(additionalUserInfo.getUsername()); + + return builder.build(); + } + + static GeneratedAndroidFirebaseAuth.PigeonAuthCredential parseAuthCredential( + AuthCredential authCredential) { + if (authCredential == null) { + return null; + } + + int authCredentialHashCode = authCredential.hashCode(); + FlutterFirebaseAuthPlugin.authCredentials.put(authCredentialHashCode, authCredential); + + GeneratedAndroidFirebaseAuth.PigeonAuthCredential.Builder builder = + new GeneratedAndroidFirebaseAuth.PigeonAuthCredential.Builder(); + + builder.setProviderId(authCredential.getProvider()); + builder.setSignInMethod(authCredential.getSignInMethod()); + builder.setNativeId((long) authCredentialHashCode); + if (authCredential instanceof OAuthCredential) { + builder.setAccessToken(((OAuthCredential) authCredential).getAccessToken()); + } + + return builder.build(); + } + + static GeneratedAndroidFirebaseAuth.PigeonUserDetails parseFirebaseUser( + FirebaseUser firebaseUser) { + if (firebaseUser == null) { + return null; + } + + GeneratedAndroidFirebaseAuth.PigeonUserDetails.Builder builder = + new GeneratedAndroidFirebaseAuth.PigeonUserDetails.Builder(); + + GeneratedAndroidFirebaseAuth.PigeonUserInfo.Builder builderInfo = + new GeneratedAndroidFirebaseAuth.PigeonUserInfo.Builder(); + + builderInfo.setDisplayName(firebaseUser.getDisplayName()); + builderInfo.setEmail(firebaseUser.getEmail()); + builderInfo.setIsEmailVerified(firebaseUser.isEmailVerified()); + builderInfo.setIsAnonymous(firebaseUser.isAnonymous()); + + final FirebaseUserMetadata userMetadata = firebaseUser.getMetadata(); + if (userMetadata != null) { + builderInfo.setCreationTimestamp(firebaseUser.getMetadata().getCreationTimestamp()); + builderInfo.setLastSignInTimestamp(firebaseUser.getMetadata().getLastSignInTimestamp()); + } + builderInfo.setPhoneNumber(firebaseUser.getPhoneNumber()); + builderInfo.setPhotoUrl(parsePhotoUrl(firebaseUser.getPhotoUrl())); + builderInfo.setUid(firebaseUser.getUid()); + builderInfo.setTenantId(firebaseUser.getTenantId()); + + builder.setUserInfo(builderInfo.build()); + builder.setProviderData(parseUserInfoList(firebaseUser.getProviderData())); + + return builder.build(); + } + + private static List> parseUserInfoList( + List userInfoList) { + List> output = new ArrayList<>(); + + if (userInfoList == null) { + return null; + } + + for (UserInfo userInfo : new ArrayList(userInfoList)) { + if (userInfo == null) { + continue; + } + if (!FirebaseAuthProvider.PROVIDER_ID.equals(userInfo.getProviderId())) { + output.add(parseUserInfoToMap(userInfo)); + } + } + + return output; + } + + private static Map parseUserInfoToMap(UserInfo userInfo) { + Map output = new HashMap<>(); + output.put("displayName", userInfo.getDisplayName()); + output.put("email", userInfo.getEmail()); + output.put("isEmailVerified", userInfo.isEmailVerified()); + output.put("phoneNumber", userInfo.getPhoneNumber()); + output.put("photoUrl", parsePhotoUrl(userInfo.getPhotoUrl())); + // Can be null on Emulator + output.put("uid", userInfo.getUid() == null ? "" : userInfo.getUid()); + output.put("providerId", userInfo.getProviderId()); + output.put("isAnonymous", false); + return output; + } + + private static String parsePhotoUrl(Uri photoUri) { + if (photoUri == null) { + return null; + } + + String photoUrl = photoUri.toString(); + + // Return null if the URL is an empty string + return "".equals(photoUrl) ? null : photoUrl; + } + + @SuppressWarnings("ConstantConditions") + static AuthCredential getCredential(Map credentialMap) { + // If the credential map contains a token, it means a native one has been stored + if (credentialMap.get(Constants.TOKEN) != null) { + int token = (int) credentialMap.get(Constants.TOKEN); + AuthCredential credential = FlutterFirebaseAuthPlugin.authCredentials.get(token); + + if (credential == null) { + throw FlutterFirebaseAuthPluginException.invalidCredential(); + } + + return credential; + } + + String signInMethod = + (String) Objects.requireNonNull(credentialMap.get(Constants.SIGN_IN_METHOD)); + String secret = (String) credentialMap.get(Constants.SECRET); + String idToken = (String) credentialMap.get(Constants.ID_TOKEN); + String accessToken = (String) credentialMap.get(Constants.ACCESS_TOKEN); + String rawNonce = (String) credentialMap.get(Constants.RAW_NONCE); + + switch (signInMethod) { + case Constants.SIGN_IN_METHOD_PASSWORD: + return EmailAuthProvider.getCredential( + (String) Objects.requireNonNull(credentialMap.get(Constants.EMAIL)), + Objects.requireNonNull(secret)); + case Constants.SIGN_IN_METHOD_EMAIL_LINK: + return EmailAuthProvider.getCredentialWithLink( + (String) Objects.requireNonNull(credentialMap.get(Constants.EMAIL)), + (String) Objects.requireNonNull(credentialMap.get(Constants.EMAIL_LINK))); + case Constants.SIGN_IN_METHOD_FACEBOOK: + return FacebookAuthProvider.getCredential(Objects.requireNonNull(accessToken)); + case Constants.SIGN_IN_METHOD_GOOGLE: + return GoogleAuthProvider.getCredential(idToken, accessToken); + case Constants.SIGN_IN_METHOD_TWITTER: + return TwitterAuthProvider.getCredential( + Objects.requireNonNull(accessToken), Objects.requireNonNull(secret)); + case Constants.SIGN_IN_METHOD_GITHUB: + return GithubAuthProvider.getCredential(Objects.requireNonNull(accessToken)); + case Constants.SIGN_IN_METHOD_PHONE: + { + String verificationId = + (String) Objects.requireNonNull(credentialMap.get(Constants.VERIFICATION_ID)); + String smsCode = (String) Objects.requireNonNull(credentialMap.get(Constants.SMS_CODE)); + return PhoneAuthProvider.getCredential(verificationId, smsCode); + } + case Constants.SIGN_IN_METHOD_OAUTH: + { + String providerId = + (String) Objects.requireNonNull(credentialMap.get(Constants.PROVIDER_ID)); + OAuthProvider.CredentialBuilder builder = OAuthProvider.newCredentialBuilder(providerId); + builder.setAccessToken(Objects.requireNonNull(accessToken)); + if (rawNonce == null) { + builder.setIdToken(Objects.requireNonNull(idToken)); + } else { + builder.setIdTokenWithRawNonce(Objects.requireNonNull(idToken), rawNonce); + } + + return builder.build(); + } + default: + return null; + } + } + + static ActionCodeSettings getActionCodeSettings( + @NonNull GeneratedAndroidFirebaseAuth.PigeonActionCodeSettings pigeonActionCodeSettings) { + ActionCodeSettings.Builder builder = ActionCodeSettings.newBuilder(); + + builder.setUrl(pigeonActionCodeSettings.getUrl()); + + if (pigeonActionCodeSettings.getDynamicLinkDomain() != null) { + builder.setDynamicLinkDomain(pigeonActionCodeSettings.getDynamicLinkDomain()); + } + + builder.setHandleCodeInApp(pigeonActionCodeSettings.getHandleCodeInApp()); + + if (pigeonActionCodeSettings.getAndroidPackageName() != null) { + builder.setAndroidPackageName( + pigeonActionCodeSettings.getAndroidPackageName(), + pigeonActionCodeSettings.getAndroidInstallApp(), + pigeonActionCodeSettings.getAndroidMinimumVersion()); + } + + if (pigeonActionCodeSettings.getIOSBundleId() != null) { + builder.setIOSBundleId(pigeonActionCodeSettings.getIOSBundleId()); + } + + return builder.build(); + } + + static List multiFactorInfoToPigeon( + List hints) { + List pigeonHints = new ArrayList<>(); + for (MultiFactorInfo info : hints) { + if (info instanceof PhoneMultiFactorInfo) { + pigeonHints.add( + new GeneratedAndroidFirebaseAuth.PigeonMultiFactorInfo.Builder() + .setPhoneNumber(((PhoneMultiFactorInfo) info).getPhoneNumber()) + .setDisplayName(info.getDisplayName()) + .setEnrollmentTimestamp((double) info.getEnrollmentTimestamp()) + .setUid(info.getUid()) + .setFactorId(info.getFactorId()) + .build()); + + } else { + pigeonHints.add( + new GeneratedAndroidFirebaseAuth.PigeonMultiFactorInfo.Builder() + .setDisplayName(info.getDisplayName()) + .setEnrollmentTimestamp((double) info.getEnrollmentTimestamp()) + .setUid(info.getUid()) + .setFactorId(info.getFactorId()) + .build()); + } + } + return pigeonHints; + } + + static List> multiFactorInfoToMap(List hints) { + List> pigeonHints = new ArrayList<>(); + for (GeneratedAndroidFirebaseAuth.PigeonMultiFactorInfo info : multiFactorInfoToPigeon(hints)) { + pigeonHints.add(info.toList()); + } + return pigeonHints; + } + + static GeneratedAndroidFirebaseAuth.PigeonActionCodeInfo parseActionCodeResult( + @NonNull ActionCodeResult actionCodeResult) { + GeneratedAndroidFirebaseAuth.PigeonActionCodeInfo.Builder builder = + new GeneratedAndroidFirebaseAuth.PigeonActionCodeInfo.Builder(); + GeneratedAndroidFirebaseAuth.PigeonActionCodeInfoData.Builder builderData = + new GeneratedAndroidFirebaseAuth.PigeonActionCodeInfoData.Builder(); + + int operation = actionCodeResult.getOperation(); + + switch (operation) { + case ActionCodeResult.PASSWORD_RESET: + builder.setOperation(GeneratedAndroidFirebaseAuth.ActionCodeInfoOperation.PASSWORD_RESET); + break; + case ActionCodeResult.VERIFY_EMAIL: + builder.setOperation(GeneratedAndroidFirebaseAuth.ActionCodeInfoOperation.VERIFY_EMAIL); + break; + case ActionCodeResult.RECOVER_EMAIL: + builder.setOperation(GeneratedAndroidFirebaseAuth.ActionCodeInfoOperation.RECOVER_EMAIL); + break; + case ActionCodeResult.SIGN_IN_WITH_EMAIL_LINK: + builder.setOperation(GeneratedAndroidFirebaseAuth.ActionCodeInfoOperation.EMAIL_SIGN_IN); + break; + case ActionCodeResult.VERIFY_BEFORE_CHANGE_EMAIL: + builder.setOperation( + GeneratedAndroidFirebaseAuth.ActionCodeInfoOperation.VERIFY_AND_CHANGE_EMAIL); + break; + case ActionCodeResult.REVERT_SECOND_FACTOR_ADDITION: + builder.setOperation( + GeneratedAndroidFirebaseAuth.ActionCodeInfoOperation.REVERT_SECOND_FACTOR_ADDITION); + break; + } + + ActionCodeInfo actionCodeInfo = actionCodeResult.getInfo(); + + if (actionCodeInfo != null && operation == ActionCodeResult.VERIFY_EMAIL + || operation == ActionCodeResult.PASSWORD_RESET) { + builderData.setEmail(actionCodeInfo.getEmail()); + } else if (operation == ActionCodeResult.RECOVER_EMAIL + || operation == ActionCodeResult.VERIFY_BEFORE_CHANGE_EMAIL) { + ActionCodeEmailInfo actionCodeEmailInfo = + (ActionCodeEmailInfo) Objects.requireNonNull(actionCodeInfo); + builderData.setEmail(actionCodeEmailInfo.getEmail()); + builderData.setPreviousEmail(actionCodeEmailInfo.getPreviousEmail()); + } + + builder.setData(builderData.build()); + + return builder.build(); + } + + static GeneratedAndroidFirebaseAuth.PigeonIdTokenResult parseTokenResult( + @NonNull GetTokenResult tokenResult) { + final GeneratedAndroidFirebaseAuth.PigeonIdTokenResult.Builder builder = + new GeneratedAndroidFirebaseAuth.PigeonIdTokenResult.Builder(); + + builder.setToken(tokenResult.getToken()); + builder.setSignInProvider(tokenResult.getSignInProvider()); + builder.setAuthTimestamp(tokenResult.getAuthTimestamp() * 1000); + builder.setExpirationTimestamp(tokenResult.getExpirationTimestamp() * 1000); + builder.setIssuedAtTimestamp(tokenResult.getIssuedAtTimestamp() * 1000); + builder.setClaims(tokenResult.getClaims()); + builder.setSignInSecondFactor(tokenResult.getSignInSecondFactor()); + + return builder.build(); + } +} diff --git a/packages/firebase_auth/firebase_auth/example/ios/Podfile b/packages/firebase_auth/firebase_auth/example/ios/Podfile index b9e967f0fdea..035ef7615d27 100644 --- a/packages/firebase_auth/firebase_auth/example/ios/Podfile +++ b/packages/firebase_auth/firebase_auth/example/ios/Podfile @@ -37,4 +37,12 @@ post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) end + + installer.generated_projects.each do |project| + project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' + end + end + end end diff --git a/packages/firebase_auth/firebase_auth/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_auth/firebase_auth/example/ios/Runner.xcodeproj/project.pbxproj index 943cdb2e457f..be1680647601 100644 --- a/packages/firebase_auth/firebase_auth/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_auth/firebase_auth/example/ios/Runner.xcodeproj/project.pbxproj @@ -226,6 +226,7 @@ files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -279,6 +280,7 @@ inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", "${BUILT_PRODUCTS_DIR}/AppAuth/AppAuth.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseAppCheckInterop/FirebaseAppCheckInterop.framework", "${BUILT_PRODUCTS_DIR}/FirebaseAuth/FirebaseAuth.framework", "${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework", "${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework", @@ -295,6 +297,7 @@ name = "[CP] Embed Pods Frameworks"; outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AppAuth.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAppCheckInterop.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAuth.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework", diff --git a/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/project.pbxproj b/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/project.pbxproj index 19e959a53be0..84ada4d1c7ec 100644 --- a/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -208,7 +208,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = "The Flutter Authors"; TargetAttributes = { 33CC10EC2044A3C60003C045 = { @@ -263,6 +263,7 @@ /* Begin PBXShellScriptBuildPhase section */ 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -327,10 +328,12 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/FirebaseAppCheckInterop/FirebaseAppCheckInterop.framework", "${BUILT_PRODUCTS_DIR}/FirebaseAuth/FirebaseAuth.framework", "${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework", "${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseInstallations/FirebaseInstallations.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseMessaging/FirebaseMessaging.framework", "${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework", "${BUILT_PRODUCTS_DIR}/GoogleDataTransport/GoogleDataTransport.framework", "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", @@ -339,10 +342,12 @@ ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAppCheckInterop.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAuth.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreDiagnostics.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessaging.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleDataTransport.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", diff --git a/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index df12c333e68c..ad089fa5dfb1 100644 --- a/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ *)registrar { // FlutterPluginRegistrar. // TODO(Salakar): addApplicationDelegate does not exist on MacOS version of // FlutterPluginRegistrar. (https://github.com/flutter/flutter/issues/41471) + FirebaseAuthHostApiSetup(registrar.messenger, instance); + FirebaseAuthUserHostApiSetup(registrar.messenger, instance); #else [registrar publish:instance]; [registrar addApplicationDelegate:instance]; + FirebaseAuthHostApiSetup(registrar.messenger, instance); + FirebaseAuthUserHostApiSetup(registrar.messenger, instance); MultiFactorUserHostApiSetup(registrar.messenger, instance); MultiFactoResolverHostApiSetup(registrar.messenger, instance); #endif } ++ (FlutterError *)convertToFlutterError:(NSError *)error { + NSString *code = @"unknown"; + NSString *message = @"An unknown error has occurred."; + + if (error == nil) { + return [FlutterError errorWithCode:code message:message details:@{}]; + } + + // code + if ([error userInfo][FIRAuthErrorUserInfoNameKey] != nil) { + // See [FIRAuthErrorCodeString] for list of codes. + // Codes are in the format "ERROR_SOME_NAME", converting below to the format + // required in Dart. ERROR_SOME_NAME -> SOME_NAME + NSString *firebaseErrorCode = [error userInfo][FIRAuthErrorUserInfoNameKey]; + code = [firebaseErrorCode stringByReplacingOccurrencesOfString:@"ERROR_" withString:@""]; + // SOME_NAME -> SOME-NAME + code = [code stringByReplacingOccurrencesOfString:@"_" withString:@"-"]; + // SOME-NAME -> some-name + code = [code lowercaseString]; + } + + // message + if ([error userInfo][NSLocalizedDescriptionKey] != nil) { + message = [error userInfo][NSLocalizedDescriptionKey]; + } + + NSMutableDictionary *additionalData = [NSMutableDictionary dictionary]; + // additionalData.email + if ([error userInfo][FIRAuthErrorUserInfoEmailKey] != nil) { + additionalData[kArgumentEmail] = [error userInfo][FIRAuthErrorUserInfoEmailKey]; + } + // additionalData.authCredential + if ([error userInfo][FIRAuthErrorUserInfoUpdatedCredentialKey] != nil) { + FIRAuthCredential *authCredential = [error userInfo][FIRAuthErrorUserInfoUpdatedCredentialKey]; + additionalData[@"authCredential"] = + [FLTFirebaseAuthPlugin getNSDictionaryFromAuthCredential:authCredential]; + } + + // Manual message overrides to ensure messages/codes matches other platforms. + if ([message isEqual:@"The password must be 6 characters long or more."]) { + message = @"Password should be at least 6 characters"; + } + + return [FlutterError errorWithCode:code message:message details:additionalData]; +} + ++ (id)getNSDictionaryFromAuthCredential:(FIRAuthCredential *)authCredential { + if (authCredential == nil) { + return [NSNull null]; + } + + NSString *accessToken = nil; + if ([authCredential isKindOfClass:[FIROAuthCredential class]]) { + if (((FIROAuthCredential *)authCredential).accessToken != nil) { + accessToken = ((FIROAuthCredential *)authCredential).accessToken; + } else if (((FIROAuthCredential *)authCredential).IDToken != nil) { + // For Sign In With Apple, the token is stored in IDToken + accessToken = ((FIROAuthCredential *)authCredential).IDToken; + } + } + + return @{ + kArgumentProviderId : authCredential.provider, + // Note: "signInMethod" does not exist on iOS SDK, so using provider + // instead. + kArgumentSignInMethod : authCredential.provider, + kArgumentToken : @([authCredential hash]), + kArgumentAccessToken : accessToken ?: [NSNull null], + }; +} + - (void)cleanupWithCompletion:(void (^)(void))completion { // Cleanup credentials. [_credentials removeAllObjects]; @@ -155,132 +232,6 @@ - (void)detachFromEngineForRegistrar:(NSObject *)registr [self cleanupWithCompletion:nil]; } -- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)flutterResult { - FLTFirebaseMethodCallErrorBlock errorBlock = - ^(NSString *_Nullable code, NSString *_Nullable message, NSDictionary *_Nullable details, - NSError *_Nullable error) { - NSMutableDictionary *generatedDetails = [NSMutableDictionary new]; - if (code == nil) { - NSDictionary *errorDetails = [FLTFirebaseAuthPlugin getNSDictionaryFromNSError:error]; - [self storeAuthCredentialIfPresent:error]; - code = errorDetails[kArgumentCode]; - message = errorDetails[@"message"]; - generatedDetails = [NSMutableDictionary dictionaryWithDictionary:errorDetails]; - } else { - generatedDetails = [NSMutableDictionary dictionaryWithDictionary:@{ - kArgumentCode : code, - @"message" : message, - @"additionalData" : @{}, - }]; - } - - if (details != nil) { - generatedDetails[@"additionalData"] = details; - } - - if ([@"unknown" isEqualToString:code]) { - NSLog(@"FLTFirebaseAuth: An error occurred while calling method %@, " - @"errorOrNil => %@", - call.method, [error userInfo]); - } - - flutterResult([FLTFirebasePlugin createFlutterErrorFromCode:code - message:message - optionalDetails:generatedDetails - andOptionalNSError:error]); - }; - - FLTFirebaseMethodCallSuccessBlock successBlock = ^(id _Nullable result) { - if ([result isKindOfClass:[FIRAuthDataResult class]]) { - flutterResult([self getNSDictionaryFromAuthResult:result]); - } else if ([result isKindOfClass:[FIRUser class]]) { - flutterResult([FLTFirebaseAuthPlugin getNSDictionaryFromUser:result]); - } else { - flutterResult(result); - } - }; - - FLTFirebaseMethodCallResult *methodCallResult = - [FLTFirebaseMethodCallResult createWithSuccess:successBlock andErrorBlock:errorBlock]; - - [self ensureAPNSTokenSetting]; - - if ([@"Auth#registerIdTokenListener" isEqualToString:call.method]) { - [self registerIdTokenListener:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#registerAuthStateListener" isEqualToString:call.method]) { - [self registerAuthStateListener:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#applyActionCode" isEqualToString:call.method]) { - [self applyActionCode:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#checkActionCode" isEqualToString:call.method]) { - [self checkActionCode:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#confirmPasswordReset" isEqualToString:call.method]) { - [self confirmPasswordReset:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#createUserWithEmailAndPassword" isEqualToString:call.method]) { - [self createUserWithEmailAndPassword:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#fetchSignInMethodsForEmail" isEqualToString:call.method]) { - [self fetchSignInMethodsForEmail:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#sendPasswordResetEmail" isEqualToString:call.method]) { - [self sendPasswordResetEmail:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#sendSignInLinkToEmail" isEqualToString:call.method]) { - [self sendSignInLinkToEmail:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#signInWithCredential" isEqualToString:call.method]) { - [self signInWithCredential:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#setLanguageCode" isEqualToString:call.method]) { - [self setLanguageCode:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#setSettings" isEqualToString:call.method]) { - [self setSettings:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#signInAnonymously" isEqualToString:call.method]) { - [self signInAnonymously:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#signInWithCustomToken" isEqualToString:call.method]) { - [self signInWithCustomToken:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#signInWithEmailAndPassword" isEqualToString:call.method]) { - [self signInWithEmailAndPassword:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#signInWithEmailLink" isEqualToString:call.method]) { - [self signInWithEmailLink:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#signOut" isEqualToString:call.method]) { - [self signOut:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#useEmulator" isEqualToString:call.method]) { - [self useEmulator:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#verifyPasswordResetCode" isEqualToString:call.method]) { - [self verifyPasswordResetCode:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#signInWithProvider" isEqualToString:call.method]) { - [self signInWithProvider:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"Auth#verifyPhoneNumber" isEqualToString:call.method]) { - [self verifyPhoneNumber:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"User#delete" isEqualToString:call.method]) { - [self userDelete:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"User#getIdToken" isEqualToString:call.method]) { - [self userGetIdToken:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"User#linkWithCredential" isEqualToString:call.method]) { - [self userLinkWithCredential:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"User#linkWithProvider" isEqualToString:call.method]) { - [self userLinkWithProvider:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"User#reauthenticateWithProvider" isEqualToString:call.method]) { - [self reauthenticateWithProvider:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"User#reauthenticateUserWithCredential" isEqualToString:call.method]) { - [self userReauthenticateUserWithCredential:call.arguments - withMethodCallResult:methodCallResult]; - } else if ([@"User#reload" isEqualToString:call.method]) { - [self userReload:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"User#sendEmailVerification" isEqualToString:call.method]) { - [self userSendEmailVerification:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"User#unlink" isEqualToString:call.method]) { - [self userUnlink:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"User#updateEmail" isEqualToString:call.method]) { - [self userUpdateEmail:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"User#updatePassword" isEqualToString:call.method]) { - [self userUpdatePassword:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"User#updatePhoneNumber" isEqualToString:call.method]) { - [self userUpdatePhoneNumber:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"User#updateProfile" isEqualToString:call.method]) { - [self userUpdateProfile:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"User#verifyBeforeUpdateEmail" isEqualToString:call.method]) { - [self userVerifyBeforeUpdateEmail:call.arguments withMethodCallResult:methodCallResult]; - } else { - methodCallResult.success(FlutterMethodNotImplemented); - } -} - #pragma mark - AppDelegate #if TARGET_OS_IPHONE @@ -329,183 +280,13 @@ - (NSDictionary *_Nonnull)pluginConstantsForFIRApp:(FIRApp *_Nonnull)firebaseApp return @{ @"APP_LANGUAGE_CODE" : (id)[auth languageCode] ?: [NSNull null], @"APP_CURRENT_USER" : [auth currentUser] - ? (id)[FLTFirebaseAuthPlugin getNSDictionaryFromUser:[auth currentUser]] + ? [[PigeonParser getPigeonDetails:[auth currentUser]] toList] : [NSNull null], }; } #pragma mark - Firebase Auth API -- (void)applyActionCode:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - [auth applyActionCode:arguments[kArgumentCode] - completion:^(NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(nil); - } - }]; -} - -- (void)checkActionCode:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - [auth checkActionCode:arguments[kArgumentCode] - completion:^(FIRActionCodeInfo *_Nullable info, NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - NSMutableDictionary *actionCodeResultDict = [NSMutableDictionary dictionary]; - NSMutableDictionary *dataDict = [NSMutableDictionary dictionary]; - - if (info.email != nil) { - dataDict[@"email"] = info.email; - } - - if (info.previousEmail != nil) { - dataDict[@"previousEmail"] = info.previousEmail; - } - - if (info.operation == FIRActionCodeOperationPasswordReset) { - actionCodeResultDict[@"operation"] = @1; - } else if (info.operation == FIRActionCodeOperationVerifyEmail) { - actionCodeResultDict[@"operation"] = @2; - } else if (info.operation == FIRActionCodeOperationRecoverEmail) { - actionCodeResultDict[@"operation"] = @3; - } else if (info.operation == FIRActionCodeOperationEmailLink) { - actionCodeResultDict[@"operation"] = @4; - } else if (info.operation == FIRActionCodeOperationVerifyAndChangeEmail) { - actionCodeResultDict[@"operation"] = @5; - } else if (info.operation == FIRActionCodeOperationRevertSecondFactorAddition) { - actionCodeResultDict[@"operation"] = @6; - } else { - // Unknown / Error. - actionCodeResultDict[@"operation"] = @0; - } - - actionCodeResultDict[@"data"] = dataDict; - - result.success(actionCodeResultDict); - } - }]; -} - -- (void)confirmPasswordReset:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - [auth confirmPasswordResetWithCode:arguments[kArgumentCode] - newPassword:arguments[@"newPassword"] - completion:^(NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(nil); - } - }]; -} - -- (void)createUserWithEmailAndPassword:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - [auth createUserWithEmail:arguments[kArgumentEmail] - password:arguments[@"password"] - completion:^(FIRAuthDataResult *authResult, NSError *error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(authResult); - } - }]; -} - -- (void)fetchSignInMethodsForEmail:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - [auth fetchSignInMethodsForEmail:arguments[kArgumentEmail] - completion:^(NSArray *_Nullable providers, - NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(@{ - @"providers" : (id)providers ?: @[], - }); - } - }]; -} - -- (void)sendPasswordResetEmail:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - NSString *email = arguments[kArgumentEmail]; - FIRActionCodeSettings *actionCodeSettings = - [self getFIRActionCodeSettingsFromArguments:arguments]; - [auth sendPasswordResetWithEmail:email - actionCodeSettings:actionCodeSettings - completion:^(NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(nil); - } - }]; -} - -- (void)sendSignInLinkToEmail:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - NSString *email = arguments[kArgumentEmail]; - FIRActionCodeSettings *actionCodeSettings = - [self getFIRActionCodeSettingsFromArguments:arguments]; - [auth sendSignInLinkToEmail:email - actionCodeSettings:actionCodeSettings - completion:^(NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(nil); - } - }]; -} - -- (void)signInWithCredential:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - FIRAuthCredential *credential = [self getFIRAuthCredentialFromArguments:arguments]; - - if (credential == nil) { - result.error(kErrCodeInvalidCredential, kErrMsgInvalidCredential, nil, nil); - return; - } - - [auth signInWithCredential:credential - completion:^(FIRAuthDataResult *authResult, NSError *error) { - if (error != nil) { - NSDictionary *userInfo = [error userInfo]; - NSError *underlyingError = [userInfo objectForKey:NSUnderlyingErrorKey]; - - NSDictionary *firebaseDictionary = - underlyingError.userInfo[@"FIRAuthErrorUserInfoDeserializedResponseKey"]; - - if (firebaseDictionary != nil && firebaseDictionary[@"message"] != nil) { - // error from firebase-ios-sdk is buried in underlying - // error. - result.error(nil, firebaseDictionary[@"message"], nil, nil); - } else { - if (error.code == FIRAuthErrorCodeSecondFactorRequired) { - [self handleMultiFactorError:arguments withResult:result withError:error]; - } else if (error.code == FIRAuthErrorCodeInternalError) { - [self handleInternalError:arguments withResult:result withError:error]; - } else { - result.error(nil, nil, nil, error); - } - } - } else { - result.success(authResult); - } - }]; -} - // Adapted from // https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce Used // for Apple Sign In @@ -558,14 +339,14 @@ static void handleSignInWithApple(FLTFirebaseAuthPlugin *object, FIRAuthDataResu if (error != nil) { if (error.code == FIRAuthErrorCodeSecondFactorRequired) { [object handleMultiFactorError:object.appleArguments - withResult:object.appleResult + completion:object.appleCompletion withError:error]; } else { - object.appleResult.error(nil, nil, nil, error); + object.appleCompletion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); } return; } - object.appleResult.success(authResult); + object.appleCompletion([PigeonParser getPigeonUserCredentialFromAuthResult:authResult], nil); } - (void)authorizationController:(ASAuthorizationController *)controller @@ -628,147 +409,67 @@ - (void)authorizationController:(ASAuthorizationController *)controller NSLog(@"Sign in with Apple errored: %@", error); switch (error.code) { case ASAuthorizationErrorCanceled: - self.appleResult.error(@"canceled", @"The user canceled the authorization attempt.", nil, - error); + self.appleCompletion( + nil, [FlutterError errorWithCode:@"canceled" + message:@"The user canceled the authorization attempt." + details:nil]); break; case ASAuthorizationErrorInvalidResponse: - self.appleResult.error(@"invalid-response", - @"The authorization request received an invalid response.", nil, - error); + self.appleCompletion( + nil, + [FlutterError errorWithCode:@"invalid-response" + message:@"The authorization request received an invalid response." + details:nil]); break; case ASAuthorizationErrorNotHandled: - self.appleResult.error(@"not-handled", @"The authorization request wasn’t handled.", nil, - error); + self.appleCompletion(nil, + [FlutterError errorWithCode:@"not-handled" + message:@"The authorization request wasn’t handled." + details:nil]); break; case ASAuthorizationErrorFailed: - self.appleResult.error(@"failed", @"The authorization attempt failed.", nil, error); + self.appleCompletion(nil, [FlutterError errorWithCode:@"failed" + message:@"The authorization attempt failed." + details:nil]); break; case ASAuthorizationErrorUnknown: default: - self.appleResult.error(nil, nil, nil, error); + self.appleCompletion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); break; } - self.appleResult = nil; -} - -- (void)signInWithProvider:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - - if ([arguments[@"signInProvider"] isEqualToString:kSignInMethodApple]) { - self.signInWithAppleAuth = auth; - launchAppleSignInRequest(self, arguments, result); - return; - } -#if TARGET_OS_OSX - NSLog(@"signInWithProvider is not supported on the " - @"MacOS platform."); - result.success(nil); -#else - self.authProvider = [FIROAuthProvider providerWithProviderID:arguments[@"signInProvider"]]; - NSArray *scopes = arguments[kArgumentProviderScope]; - if (scopes != nil) { - [self.authProvider setScopes:scopes]; - } - NSDictionary *customParameters = arguments[kArgumentProviderCustomParameters]; - if (customParameters != nil) { - [self.authProvider setCustomParameters:customParameters]; - } - - [self.authProvider - getCredentialWithUIDelegate:nil - completion:^(FIRAuthCredential *_Nullable credential, - NSError *_Nullable error) { - handleAppleAuthResult(self, arguments, auth, credential, error, result); - }]; -#endif -} - -- (void)setLanguageCode:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - NSString *languageCode = arguments[@"languageCode"]; - - if (languageCode != nil && ![languageCode isEqual:[NSNull null]]) { - auth.languageCode = languageCode; - } else { - [auth useAppLanguage]; - } - - result.success(@{@"languageCode" : auth.languageCode}); -} - -- (void)setSettings:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - - if ([[arguments allKeys] containsObject:@"userAccessGroup"] && - ![arguments[@"userAccessGroup"] isEqual:[NSNull null]]) { - BOOL useUserAccessGroupSuccessful; - NSError *useUserAccessGroupErrorPtr; - useUserAccessGroupSuccessful = [auth useUserAccessGroup:arguments[@"userAccessGroup"] - error:&useUserAccessGroupErrorPtr]; - if (!useUserAccessGroupSuccessful) { - return result.error(nil, nil, nil, useUserAccessGroupErrorPtr); - } - } - -#if TARGET_OS_IPHONE - if ([[arguments allKeys] containsObject:@"appVerificationDisabledForTesting"] && - ![arguments[@"appVerificationDisabledForTesting"] isEqual:[NSNull null]]) { - auth.settings.appVerificationDisabledForTesting = - [arguments[@"appVerificationDisabledForTesting"] boolValue]; - } -#else - NSLog(@"FIRAuthSettings.appVerificationDisabledForTesting is not supported " - @"on MacOS."); -#endif - - result.success(nil); -} - -- (void)signInWithCustomToken:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - - [auth signInWithCustomToken:arguments[kArgumentToken] - completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) { - if (error != nil) { - if (error.code == FIRAuthErrorCodeSecondFactorRequired) { - [self handleMultiFactorError:arguments withResult:result withError:error]; - } else if (error.code == FIRAuthErrorCodeInternalError) { - [self handleInternalError:arguments withResult:result withError:error]; - } else { - result.error(nil, nil, nil, error); - } - } else { - result.success(authResult); - } - }]; + self.appleCompletion = nil; } -- (void)handleInternalError:(id)arguments - withResult:(FLTFirebaseMethodCallResult *)result +- (void)handleInternalError:(nonnull void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion withError:(NSError *)error { const NSError *underlyingError = error.userInfo[@"NSUnderlyingError"]; if (underlyingError != nil) { const NSDictionary *details = underlyingError.userInfo[@"FIRAuthErrorUserInfoDeserializedResponseKey"]; - result.error(nil, nil, details, underlyingError); + completion(nil, [FlutterError errorWithCode:@"internal-error" + message:error.description + details:details]); return; } - result.error(nil, nil, nil, error); + completion(nil, [FlutterError errorWithCode:@"internal-error" + message:error.description + details:nil]); } -- (void)handleMultiFactorError:(id)arguments - withResult:(FLTFirebaseMethodCallResult *)result +- (void)handleMultiFactorError:(PigeonFirebaseApp *)app + completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion withError:(NSError *_Nullable)error { #if TARGET_OS_OSX - result.error(nil, nil, nil, error); + completion(nil, [FlutterError errorWithCode:@"multi-factor-auth-required" + message:error.description + details:nil]); #else - FIRMultiFactorResolver *resolver = (FIRMultiFactorResolver *)error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey]; @@ -798,178 +499,39 @@ - (void)handleMultiFactorError:(id)arguments uid:multiFactorInfo.UID phoneNumber:phoneNumber]; - [pigeonHints addObject:object.toMap]; + [pigeonHints addObject:object.toList]; } NSDictionary *output = @{ - kAppName : arguments[kAppName], + kAppName : app.appName, kArgumentMultiFactorHints : pigeonHints, kArgumentMultiFactorSessionId : sessionId, kArgumentMultiFactorResolverId : resolverId, }; - result.error(nil, nil, output, error); + completion(nil, [FlutterError errorWithCode:@"multi-factor-auth-required" + message:error.description + details:output]); #endif } -- (void)signInWithEmailAndPassword:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - [auth signInWithEmail:arguments[kArgumentEmail] - password:arguments[@"password"] - completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) { - if (error != nil) { - if (error.code == FIRAuthErrorCodeSecondFactorRequired) { - [self handleMultiFactorError:arguments withResult:result withError:error]; - } else if (error.code == FIRAuthErrorCodeInternalError) { - [self handleInternalError:arguments withResult:result withError:error]; - } else { - result.error(nil, nil, nil, error); - } - } else { - result.success(authResult); - } - }]; -} - -- (void)signInWithEmailLink:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - [auth signInWithEmail:arguments[kArgumentEmail] - link:arguments[@"emailLink"] - completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) { - if (error != nil) { - if (error.code == FIRAuthErrorCodeSecondFactorRequired) { - [self handleMultiFactorError:arguments withResult:result withError:error]; - } else if (error.code == FIRAuthErrorCodeInternalError) { - [self handleInternalError:arguments withResult:result withError:error]; - } else { - result.error(nil, nil, nil, error); - } - } else { - result.success(authResult); - } - }]; -} - -- (void)signOut:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; +static void launchAppleSignInRequest(FLTFirebaseAuthPlugin *object, PigeonFirebaseApp *app, + PigeonSignInProvider *signInProvider, + void (^_Nonnull completion)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable)) { + if (@available(iOS 13.0, macOS 10.15, *)) { + NSString *nonce = [object randomNonce:32]; + object.currentNonce = nonce; + object.appleCompletion = completion; + object.appleArguments = app; - if (auth.currentUser == nil) { - result.success(nil); - return; - } - - NSError *signOutErrorPtr; - BOOL signOutSuccessful = [auth signOut:&signOutErrorPtr]; - - if (!signOutSuccessful) { - result.error(nil, nil, nil, signOutErrorPtr); - } else { - result.success(nil); - } -} - -- (void)useEmulator:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - [auth useEmulatorWithHost:arguments[@"host"] port:[arguments[@"port"] integerValue]]; - result.success(nil); -} - -- (void)verifyPasswordResetCode:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - - [auth verifyPasswordResetCode:arguments[kArgumentCode] - completion:^(NSString *_Nullable email, NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(@{kArgumentEmail : (id)email ?: [NSNull null]}); - } - }]; -} - -- (void)userDelete:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - FIRUser *currentUser = auth.currentUser; - if (currentUser == nil) { - result.error(kErrCodeNoCurrentUser, kErrMsgNoCurrentUser, nil, nil); - return; - } - - [currentUser deleteWithCompletion:^(NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(nil); - } - }]; -} - -- (void)userGetIdToken:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - FIRUser *currentUser = auth.currentUser; - if (currentUser == nil) { - result.error(kErrCodeNoCurrentUser, kErrMsgNoCurrentUser, nil, nil); - return; - } - - BOOL forceRefresh = [arguments[@"forceRefresh"] boolValue]; - BOOL tokenOnly = [arguments[@"tokenOnly"] boolValue]; - - [currentUser - getIDTokenResultForcingRefresh:forceRefresh - completion:^(FIRAuthTokenResult *tokenResult, NSError *error) { - if (error != nil) { - result.error(nil, nil, nil, error); - return; - } - - if (tokenOnly) { - result.success( - @{kArgumentToken : (id)tokenResult.token ?: [NSNull null]}); - } else { - long expirationTimestamp = - (long)[tokenResult.expirationDate timeIntervalSince1970] * 1000; - long authTimestamp = - (long)[tokenResult.authDate timeIntervalSince1970] * 1000; - long issuedAtTimestamp = - (long)[tokenResult.issuedAtDate timeIntervalSince1970] * 1000; - - NSMutableDictionary *tokenData = - [[NSMutableDictionary alloc] initWithDictionary:@{ - @"authTimestamp" : @(authTimestamp), - @"claims" : tokenResult.claims, - @"expirationTimestamp" : @(expirationTimestamp), - @"issuedAtTimestamp" : @(issuedAtTimestamp), - @"signInProvider" : (id)tokenResult.signInProvider - ?: [NSNull null], - @"signInSecondFactor" : (id)tokenResult.signInSecondFactor - ?: [NSNull null], - kArgumentToken : tokenResult.token, - }]; - - result.success(tokenData); - } - }]; -} - -static void launchAppleSignInRequest(FLTFirebaseAuthPlugin *object, id arguments, - FLTFirebaseMethodCallResult *result) { - if (@available(iOS 13.0, macOS 10.15, *)) { - NSString *nonce = [object randomNonce:32]; - object.currentNonce = nonce; - object.appleResult = result; - object.appleArguments = arguments; - - ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init]; + ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init]; ASAuthorizationAppleIDRequest *request = [appleIDProvider createRequest]; NSMutableArray *requestedScopes = [NSMutableArray arrayWithCapacity:2]; - if ([arguments[kArgumentProviderScope] containsObject:@"name"]) { + if ([signInProvider.scopes containsObject:@"name"]) { [requestedScopes addObject:ASAuthorizationScopeFullName]; } - if ([arguments[kArgumentProviderScope] containsObject:@"email"]) { + if ([signInProvider.scopes containsObject:@"email"]) { [requestedScopes addObject:ASAuthorizationScopeEmail]; } request.requestedScopes = [requestedScopes copy]; @@ -986,14 +548,17 @@ static void launchAppleSignInRequest(FLTFirebaseAuthPlugin *object, id arguments } } -static void handleAppleAuthResult(FLTFirebaseAuthPlugin *object, id arguments, FIRAuth *auth, - FIRAuthCredential *credentials, NSError *error, - FLTFirebaseMethodCallResult *result) { +static void handleAppleAuthResult(FLTFirebaseAuthPlugin *object, PigeonFirebaseApp *app, + FIRAuth *auth, FIRAuthCredential *credentials, NSError *error, + void (^_Nonnull completion)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable)) { if (error) { if (error.code == FIRAuthErrorCodeSecondFactorRequired) { - [object handleMultiFactorError:arguments withResult:result withError:error]; + [object handleMultiFactorError:app completion:completion withError:error]; } else { - result.error(nil, nil, nil, error); + completion(nil, [FlutterError errorWithCode:@"sign-in-failed" + message:error.localizedDescription + details:error.userInfo]); } return; } @@ -1011,413 +576,351 @@ static void handleAppleAuthResult(FLTFirebaseAuthPlugin *object, id arguments, F if (firebaseDictionary != nil && firebaseDictionary[@"message"] != nil) { // error from firebase-ios-sdk is // buried in underlying error. - result.error(nil, firebaseDictionary[@"message"], nil, nil); + completion(nil, + [FlutterError errorWithCode:@"sign-in-failed" + message:error.localizedDescription + details:firebaseDictionary[@"message"]]); } else { - result.error(nil, nil, nil, error); + completion(nil, [FlutterError errorWithCode:@"sign-in-failed" + message:error.localizedDescription + details:error.userInfo]); } } else { - result.success(authResult); + completion([PigeonParser getPigeonUserCredentialFromAuthResult:authResult], + nil); } }]; } } -- (void)userLinkWithProvider:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - - FIRUser *currentUser = auth.currentUser; - if (currentUser == nil) { - result.error(kErrCodeNoCurrentUser, kErrMsgNoCurrentUser, nil, nil); - return; - } +#pragma mark - Utilities - if ([arguments[@"signInProvider"] isEqualToString:kSignInMethodApple]) { - self.linkWithAppleUser = currentUser; - launchAppleSignInRequest(self, arguments, result); - return; - } -#if TARGET_OS_OSX - NSLog(@"linkWithProvider is not supported on the " - @"MacOS platform."); - result.success(nil); -#else - self.authProvider = [FIROAuthProvider providerWithProviderID:arguments[@"signInProvider"]]; - NSArray *scopes = arguments[kArgumentProviderScope]; - if (scopes != nil) { - [self.authProvider setScopes:scopes]; - } - NSDictionary *customParameters = arguments[kArgumentProviderCustomParameters]; - if (customParameters != nil) { - [self.authProvider setCustomParameters:customParameters]; +- (void)storeAuthCredentialIfPresent:(NSError *)error { + if ([error userInfo][FIRAuthErrorUserInfoUpdatedCredentialKey] != nil) { + FIRAuthCredential *authCredential = [error userInfo][FIRAuthErrorUserInfoUpdatedCredentialKey]; + // We temporarily store the non-serializable credential so the + // Dart API can consume these at a later time. + NSNumber *authCredentialHash = @([authCredential hash]); + _credentials[authCredentialHash] = authCredential; } - - [currentUser - linkWithProvider:self.authProvider - UIDelegate:nil - completion:^(FIRAuthDataResult *authResult, NSError *error) { - handleAppleAuthResult(self, arguments, auth, authResult.credential, error, result); - }]; -#endif } -- (void)reauthenticateWithProvider:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; +- (FIRAuth *_Nullable)getFIRAuthFromAppNameFromPigeon:(PigeonFirebaseApp *)pigeonApp { + FIRApp *app = [FLTFirebasePlugin firebaseAppNamed:pigeonApp.appName]; + FIRAuth *auth = [FIRAuth authWithApp:app]; - FIRUser *currentUser = auth.currentUser; - if (currentUser == nil) { - result.error(kErrCodeNoCurrentUser, kErrMsgNoCurrentUser, nil, nil); - return; - } + return auth; +} - if ([arguments[@"signInProvider"] isEqualToString:kSignInMethodApple]) { - self.isReauthenticatingWithApple = YES; - launchAppleSignInRequest(self, arguments, result); - return; - } -#if TARGET_OS_OSX - NSLog(@"reauthenticateWithProvider is not supported on the " - @"MacOS platform."); - result.success(nil); -#else - self.authProvider = [FIROAuthProvider providerWithProviderID:arguments[@"signInProvider"]]; - NSArray *scopes = arguments[kArgumentProviderScope]; - if (scopes != nil) { - [self.authProvider setScopes:scopes]; - } - NSDictionary *customParameters = arguments[kArgumentProviderCustomParameters]; - if (customParameters != nil) { - [self.authProvider setCustomParameters:customParameters]; +- (FIRAuthCredential *_Nullable)getFIRAuthCredentialFromArguments:(NSDictionary *)arguments + app:(PigeonFirebaseApp *)app { + // If the credential dictionary contains a token, it means a native one has + // been stored for later usage, so we'll attempt to retrieve it here. + if (arguments[kArgumentToken] != nil && ![arguments[kArgumentToken] isEqual:[NSNull null]]) { + NSNumber *credentialHashCode = arguments[kArgumentToken]; + return _credentials[credentialHashCode]; } - [currentUser reauthenticateWithProvider:self.authProvider - UIDelegate:nil - completion:^(FIRAuthDataResult *authResult, NSError *error) { - handleAppleAuthResult(self, arguments, auth, authResult.credential, - error, result); - }]; -#endif -} - -- (void)userLinkWithCredential:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; + NSString *signInMethod = arguments[kArgumentSignInMethod]; + NSString *secret = arguments[kArgumentSecret] == [NSNull null] ? nil : arguments[kArgumentSecret]; + NSString *idToken = + arguments[kArgumentIdToken] == [NSNull null] ? nil : arguments[kArgumentIdToken]; + NSString *accessToken = + arguments[kArgumentAccessToken] == [NSNull null] ? nil : arguments[kArgumentAccessToken]; + NSString *rawNonce = + arguments[kArgumentRawNonce] == [NSNull null] ? nil : arguments[kArgumentRawNonce]; - FIRUser *currentUser = auth.currentUser; - if (currentUser == nil) { - result.error(kErrCodeNoCurrentUser, kErrMsgNoCurrentUser, nil, nil); - return; + // Password Auth + if ([signInMethod isEqualToString:kSignInMethodPassword]) { + NSString *email = arguments[kArgumentEmail]; + return [FIREmailAuthProvider credentialWithEmail:email password:secret]; } - FIRAuthCredential *credential = [self getFIRAuthCredentialFromArguments:arguments]; - if (credential == nil) { - result.error(kErrCodeInvalidCredential, kErrMsgInvalidCredential, nil, nil); - return; + // Email Link Auth + if ([signInMethod isEqualToString:kSignInMethodEmailLink]) { + NSString *email = arguments[kArgumentEmail]; + NSString *emailLink = arguments[kArgumentEmailLink]; + return [FIREmailAuthProvider credentialWithEmail:email link:emailLink]; } - [currentUser linkWithCredential:credential - completion:^(FIRAuthDataResult *authResult, NSError *error) { - if (error != nil) { - if (error.code == FIRAuthErrorCodeSecondFactorRequired) { - [self handleMultiFactorError:arguments - withResult:result - withError:error]; - } else { - result.error(nil, nil, nil, error); - } - } else { - result.success(authResult); - } - }]; -} - -- (void)userReauthenticateUserWithCredential:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - - FIRUser *currentUser = auth.currentUser; - if (currentUser == nil) { - result.error(kErrCodeNoCurrentUser, kErrMsgNoCurrentUser, nil, nil); - return; + // Facebook Auth + if ([signInMethod isEqualToString:kSignInMethodFacebook]) { + return [FIRFacebookAuthProvider credentialWithAccessToken:accessToken]; } - FIRAuthCredential *credential = [self getFIRAuthCredentialFromArguments:arguments]; - if (credential == nil) { - result.error(kErrCodeInvalidCredential, kErrMsgInvalidCredential, nil, nil); - return; + // Google Auth + if ([signInMethod isEqualToString:kSignInMethodGoogle]) { + return [FIRGoogleAuthProvider credentialWithIDToken:idToken accessToken:accessToken]; } - [currentUser reauthenticateWithCredential:credential - completion:^(FIRAuthDataResult *authResult, NSError *error) { - if (error != nil) { - if (error.code == FIRAuthErrorCodeSecondFactorRequired) { - [self handleMultiFactorError:arguments - withResult:result - withError:error]; - } else { - result.error(nil, nil, nil, error); - } - } else { - result.success(authResult); - } - }]; -} - -- (void)userReload:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - FIRUser *currentUser = auth.currentUser; - if (currentUser == nil) { - result.error(kErrCodeNoCurrentUser, kErrMsgNoCurrentUser, nil, nil); - return; + // Twitter Auth + if ([signInMethod isEqualToString:kSignInMethodTwitter]) { + return [FIRTwitterAuthProvider credentialWithToken:accessToken secret:secret]; } - [currentUser reloadWithCompletion:^(NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(auth.currentUser); - } - }]; -} - -- (void)userSendEmailVerification:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - FIRUser *currentUser = auth.currentUser; - if (currentUser == nil) { - result.error(kErrCodeNoCurrentUser, kErrMsgNoCurrentUser, nil, nil); - return; + // GitHub Auth + if ([signInMethod isEqualToString:kSignInMethodGithub]) { + return [FIRGitHubAuthProvider credentialWithToken:accessToken]; } - FIRActionCodeSettings *actionCodeSettings = - [self getFIRActionCodeSettingsFromArguments:arguments]; - [currentUser sendEmailVerificationWithActionCodeSettings:actionCodeSettings - completion:^(NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(nil); - } - }]; -} + // Phone Auth - Only supported on iOS + if ([signInMethod isEqualToString:kSignInMethodPhone]) { +#if TARGET_OS_IPHONE + NSString *verificationId = arguments[kArgumentVerificationId]; + NSString *smsCode = arguments[kArgumentSmsCode]; + return [[FIRPhoneAuthProvider providerWithAuth:[self getFIRAuthFromAppNameFromPigeon:app]] + credentialWithVerificationID:verificationId + verificationCode:smsCode]; +#else + NSLog(@"The Firebase Phone Authentication provider is not supported on the " + @"MacOS platform."); + return nil; +#endif + } -- (void)userUnlink:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - FIRUser *currentUser = auth.currentUser; - if (currentUser == nil) { - result.error(kErrCodeNoCurrentUser, kErrMsgNoCurrentUser, nil, nil); - return; + // OAuth + if ([signInMethod isEqualToString:kSignInMethodOAuth]) { + NSString *providerId = arguments[kArgumentProviderId]; + return [FIROAuthProvider credentialWithProviderID:providerId + IDToken:idToken + rawNonce:rawNonce + accessToken:accessToken]; } - [currentUser - unlinkFromProvider:arguments[kArgumentProviderId] - completion:^(FIRUser *_Nullable user, NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - [auth.currentUser reloadWithCompletion:^(NSError *_Nullable reloadError) { - if (reloadError != nil) { - result.error(nil, nil, nil, reloadError); - } else { - // Note: On other SDKs `unlinkFromProvider` returns an - // AuthResult instance, whereas the iOS SDK currently - // does not, so we manualy construct a Dart - // representation of one here. - result.success(@{ - @"additionalUserInfo" : [NSNull null], - @"authCredential" : [NSNull null], - @"user" : auth.currentUser - ? [FLTFirebaseAuthPlugin getNSDictionaryFromUser:auth.currentUser] - : [NSNull null], - }); - } - }]; - } - }]; + NSLog(@"Support for an auth provider with identifier '%@' is not implemented.", signInMethod); + return nil; } -- (void)userUpdateEmail:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - FIRUser *currentUser = auth.currentUser; - if (currentUser == nil) { - result.error(kErrCodeNoCurrentUser, kErrMsgNoCurrentUser, nil, nil); - return; +- (void)ensureAPNSTokenSetting { +#if !TARGET_OS_OSX + FIRApp *defaultApp = [FIRApp defaultApp]; + if (defaultApp) { + if ([FIRAuth auth].APNSToken == nil && _apnsToken != nil) { + [[FIRAuth auth] setAPNSToken:_apnsToken type:FIRAuthAPNSTokenTypeUnknown]; + _apnsToken = nil; + } } - - [currentUser updateEmail:arguments[kArgumentNewEmail] - completion:^(NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - [currentUser reloadWithCompletion:^(NSError *_Nullable reloadError) { - if (reloadError != nil) { - result.error(nil, nil, nil, reloadError); - } else { - result.success(auth.currentUser); - } - }]; - } - }]; +#endif } -- (void)userUpdatePassword:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; +#if !TARGET_OS_OSX +- (FIRMultiFactor *)getAppMultiFactorFromPigeon:(nonnull PigeonFirebaseApp *)app { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; FIRUser *currentUser = auth.currentUser; - if (currentUser == nil) { - result.error(kErrCodeNoCurrentUser, kErrMsgNoCurrentUser, nil, nil); - return; - } + return currentUser.multiFactor; +} +#endif - [currentUser updatePassword:arguments[@"newPassword"] - completion:^(NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - [currentUser reloadWithCompletion:^(NSError *_Nullable reloadError) { - if (reloadError != nil) { - result.error(nil, nil, nil, reloadError); - } else { - result.success(auth.currentUser); - } - }]; - } - }]; +- (nonnull ASPresentationAnchor)presentationAnchorForAuthorizationController: + (nonnull ASAuthorizationController *)controller API_AVAILABLE(macos(10.15), ios(13.0)) { +#if TARGET_OS_OSX + return [[NSApplication sharedApplication] keyWindow]; +#else + return [[UIApplication sharedApplication] keyWindow]; +#endif } -- (void)userUpdatePhoneNumber:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { #if TARGET_OS_IPHONE - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - FIRUser *currentUser = auth.currentUser; - if (currentUser == nil) { - result.error(kErrCodeNoCurrentUser, kErrMsgNoCurrentUser, nil, nil); - return; - } +- (void)enrollPhoneApp:(nonnull PigeonFirebaseApp *)app + assertion:(nonnull PigeonPhoneMultiFactorAssertion *)assertion + displayName:(nullable NSString *)displayName + completion:(nonnull void (^)(FlutterError *_Nullable))completion { + FIRMultiFactor *multiFactor = [self getAppMultiFactorFromPigeon:app]; - FIRAuthCredential *credential = [self getFIRAuthCredentialFromArguments:arguments]; - if (credential == nil) { - result.error(kErrCodeInvalidCredential, kErrMsgInvalidCredential, nil, nil); - return; - } + FIRPhoneAuthCredential *credential = + [[FIRPhoneAuthProvider providerWithAuth:[self getFIRAuthFromAppNameFromPigeon:app]] + credentialWithVerificationID:[assertion verificationId] + verificationCode:[assertion verificationCode]]; - [currentUser - updatePhoneNumberCredential:(FIRPhoneAuthCredential *)credential - completion:^(NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - [currentUser reloadWithCompletion:^(NSError *_Nullable reloadError) { - if (reloadError != nil) { - result.error(nil, nil, nil, reloadError); - } else { - result.success(auth.currentUser); - } - }]; - } - }]; -#else - NSLog(@"Updating a users phone number via Firebase Authentication is only " - @"supported on the iOS " - @"platform."); - result.success(nil); -#endif + FIRMultiFactorAssertion *multiFactorAssertion = + [FIRPhoneMultiFactorGenerator assertionWithCredential:credential]; + + [multiFactor enrollWithAssertion:multiFactorAssertion + displayName:displayName + completion:^(NSError *_Nullable error) { + if (error == nil) { + completion(nil); + } else { + completion([FlutterError errorWithCode:@"enroll-failed" + message:error.localizedDescription + details:nil]); + } + }]; } -- (void)userUpdateProfile:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - FIRUser *currentUser = auth.currentUser; - if (currentUser == nil) { - result.error(kErrCodeNoCurrentUser, kErrMsgNoCurrentUser, nil, nil); - return; - } +- (void)getEnrolledFactorsApp:(nonnull PigeonFirebaseApp *)app + completion:(nonnull void (^)(NSArray *_Nullable, + FlutterError *_Nullable))completion { + FIRMultiFactor *multiFactor = [self getAppMultiFactorFromPigeon:app]; - NSDictionary *profileUpdates = arguments[@"profile"]; - FIRUserProfileChangeRequest *changeRequest = [currentUser profileChangeRequest]; + NSArray *enrolledFactors = [multiFactor enrolledFactors]; - if (profileUpdates[@"displayName"] != nil) { - if ([profileUpdates[@"displayName"] isEqual:[NSNull null]]) { - changeRequest.displayName = nil; - } else { - changeRequest.displayName = profileUpdates[@"displayName"]; - } - } + NSMutableArray *results = [NSMutableArray array]; - if (profileUpdates[@"photoURL"] != nil) { - if ([profileUpdates[@"photoURL"] isEqual:[NSNull null]]) { - // We apparently cannot set photoURL to nil/NULL to remove it. - // Instead, setting it to empty string appears to work. - // When doing so, Dart will properly receive `null` anyway. - changeRequest.photoURL = [NSURL URLWithString:@""]; - } else { - changeRequest.photoURL = [NSURL URLWithString:profileUpdates[@"photoURL"]]; + for (FIRMultiFactorInfo *multiFactorInfo in enrolledFactors) { + NSString *phoneNumber; + if ([multiFactorInfo class] == [FIRPhoneMultiFactorInfo class]) { + FIRPhoneMultiFactorInfo *phoneFactorInfo = (FIRPhoneMultiFactorInfo *)multiFactorInfo; + phoneNumber = phoneFactorInfo.phoneNumber; } + + [results + addObject:[PigeonMultiFactorInfo + makeWithDisplayName:multiFactorInfo.displayName + enrollmentTimestamp:[NSNumber numberWithDouble:multiFactorInfo.enrollmentDate + .timeIntervalSince1970] + factorId:multiFactorInfo.factorID + uid:multiFactorInfo.UID + phoneNumber:phoneNumber]]; } - [changeRequest commitChangesWithCompletion:^(NSError *error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - [currentUser reloadWithCompletion:^(NSError *_Nullable reloadError) { - if (reloadError != nil) { - result.error(nil, nil, nil, reloadError); - } else { - result.success(auth.currentUser); - } - }]; - } + completion(results, nil); +} + +- (void)getSessionApp:(nonnull PigeonFirebaseApp *)app + completion:(nonnull void (^)(PigeonMultiFactorSession *_Nullable, + FlutterError *_Nullable))completion { + FIRMultiFactor *multiFactor = [self getAppMultiFactorFromPigeon:app]; + [multiFactor getSessionWithCompletion:^(FIRMultiFactorSession *_Nullable session, + NSError *_Nullable error) { + NSString *UUID = [[NSUUID UUID] UUIDString]; + self->_multiFactorSessionMap[UUID] = session; + + PigeonMultiFactorSession *pigeonSession = [PigeonMultiFactorSession makeWithId:UUID]; + completion(pigeonSession, nil); }]; } -- (void)userVerifyBeforeUpdateEmail:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; +- (void)unenrollApp:(nonnull PigeonFirebaseApp *)app + factorUid:(nonnull NSString *)factorUid + completion:(nonnull void (^)(FlutterError *_Nullable))completion { + FIRMultiFactor *multiFactor = [self getAppMultiFactorFromPigeon:app]; + [multiFactor unenrollWithFactorUID:factorUid + completion:^(NSError *_Nullable error) { + if (error == nil) { + completion(nil); + } else { + completion([FlutterError errorWithCode:@"unenroll-failed" + message:error.localizedDescription + details:nil]); + } + }]; +} + +- (void)resolveSignInResolverId:(nonnull NSString *)resolverId + assertion:(nonnull PigeonPhoneMultiFactorAssertion *)assertion + completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion { + FIRMultiFactorResolver *resolver = _multiFactorResolverMap[resolverId]; + + FIRPhoneAuthCredential *credential = + [[FIRPhoneAuthProvider provider] credentialWithVerificationID:[assertion verificationId] + verificationCode:[assertion verificationCode]]; - FIRUser *currentUser = auth.currentUser; - if (currentUser == nil) { - result.error(kErrCodeNoCurrentUser, kErrMsgNoCurrentUser, nil, nil); - return; - } + FIRMultiFactorAssertion *multiFactorAssertion = + [FIRPhoneMultiFactorGenerator assertionWithCredential:credential]; - NSString *newEmail = arguments[kArgumentNewEmail]; - FIRActionCodeSettings *actionCodeSettings = - [self getFIRActionCodeSettingsFromArguments:arguments]; - [currentUser sendEmailVerificationBeforeUpdatingEmail:newEmail - actionCodeSettings:actionCodeSettings - completion:^(NSError *error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(nil); - } - }]; + [resolver + resolveSignInWithAssertion:multiFactorAssertion + completion:^(FIRAuthDataResult *_Nullable authResult, + NSError *_Nullable error) { + if (error == nil) { + completion( + [PigeonParser getPigeonUserCredentialFromAuthResult:authResult], nil); + } else { + completion(nil, [FlutterError errorWithCode:@"resolve-signin-failed" + message:error.localizedDescription + details:nil]); + } + }]; } -- (void)registerIdTokenListener:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; +#endif - NSString *name = - [NSString stringWithFormat:@"%@/id-token/%@", kFLTFirebaseAuthChannelName, auth.app.name]; +- (void)applyActionCodeApp:(nonnull PigeonFirebaseApp *)app + code:(nonnull NSString *)code + completion:(nonnull void (^)(FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + [auth applyActionCode:code + completion:^(NSError *_Nullable error) { + if (error != nil) { + completion([FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + completion(nil); + } + }]; +} - FlutterEventChannel *channel = [FlutterEventChannel eventChannelWithName:name - binaryMessenger:_binaryMessenger]; +- (void)checkActionCodeApp:(nonnull PigeonFirebaseApp *)app + code:(nonnull NSString *)code + completion:(nonnull void (^)(PigeonActionCodeInfo *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + [auth checkActionCode:code + completion:^(FIRActionCodeInfo *_Nullable info, NSError *_Nullable error) { + if (error != nil) { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + completion([PigeonParser parseActionCode:info], nil); + } + }]; +} - FLTIdTokenChannelStreamHandler *handler = - [[FLTIdTokenChannelStreamHandler alloc] initWithAuth:auth]; - [channel setStreamHandler:handler]; +- (void)confirmPasswordResetApp:(nonnull PigeonFirebaseApp *)app + code:(nonnull NSString *)code + newPassword:(nonnull NSString *)newPassword + completion:(nonnull void (^)(FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + [auth confirmPasswordResetWithCode:code + newPassword:newPassword + completion:^(NSError *_Nullable error) { + if (error != nil) { + completion([FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + completion(nil); + } + }]; +} - [_eventChannels setObject:channel forKey:name]; - [_streamHandlers setObject:handler forKey:name]; +- (void)createUserWithEmailAndPasswordApp:(nonnull PigeonFirebaseApp *)app + email:(nonnull NSString *)email + password:(nonnull NSString *)password + completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + [auth + createUserWithEmail:email + password:password + completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) { + if (error != nil) { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + completion([PigeonParser getPigeonUserCredentialFromAuthResult:authResult], nil); + } + }]; +} - result.success(name); +- (void)fetchSignInMethodsForEmailApp:(nonnull PigeonFirebaseApp *)app + email:(nonnull NSString *)email + completion:(nonnull void (^)(NSArray *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + [auth fetchSignInMethodsForEmail:email + completion:^(NSArray *_Nullable providers, + NSError *_Nullable error) { + if (error != nil) { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + completion(providers, nil); + } + }]; } -- (void)registerAuthStateListener:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; +- (void)registerAuthStateListenerApp:(nonnull PigeonFirebaseApp *)app + completion:(nonnull void (^)(NSString *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; NSString *name = [NSString stringWithFormat:@"%@/auth-state/%@", kFLTFirebaseAuthChannelName, auth.app.name]; @@ -1431,534 +934,831 @@ - (void)registerAuthStateListener:(id)arguments [_eventChannels setObject:channel forKey:name]; [_streamHandlers setObject:handler forKey:name]; - result.success(name); + completion(name, nil); } -- (void)signInAnonymously:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; - [auth signInAnonymouslyWithCompletion:^(FIRAuthDataResult *authResult, NSError *error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(authResult); - } - }]; -} +- (void)registerIdTokenListenerApp:(nonnull PigeonFirebaseApp *)app + completion:(nonnull void (^)(NSString *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; -- (void)verifyPhoneNumber:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { -#if TARGET_OS_OSX - NSLog(@"The Firebase Phone Authentication provider is not supported on the " - @"MacOS platform."); - result.success(nil); -#else - FIRAuth *auth = [self getFIRAuthFromArguments:arguments]; + NSString *name = + [NSString stringWithFormat:@"%@/id-token/%@", kFLTFirebaseAuthChannelName, auth.app.name]; - NSString *name = [NSString - stringWithFormat:@"%@/phone/%@", kFLTFirebaseAuthChannelName, [NSUUID UUID].UUIDString]; FlutterEventChannel *channel = [FlutterEventChannel eventChannelWithName:name binaryMessenger:_binaryMessenger]; - NSString *multiFactorSessionId = arguments[kArgumentMultiFactorSessionId]; - FIRMultiFactorSession *multiFactorSession = nil; - - if (multiFactorSessionId != nil) { - multiFactorSession = _multiFactorSessionMap[multiFactorSessionId]; - } - - NSString *multiFactorInfoId = arguments[kArgumentMultiFactorInfo]; - - FIRPhoneMultiFactorInfo *multiFactorInfo = nil; - if (multiFactorInfoId != nil) { - for (NSString *resolverId in _multiFactorResolverMap) { - for (FIRMultiFactorInfo *info in _multiFactorResolverMap[resolverId].hints) { - if ([info.UID isEqualToString:multiFactorInfoId] && - [info class] == [FIRPhoneMultiFactorInfo class]) { - multiFactorInfo = (FIRPhoneMultiFactorInfo *)info; - break; - } - } - } - } - - FLTPhoneNumberVerificationStreamHandler *handler = - [[FLTPhoneNumberVerificationStreamHandler alloc] initWithAuth:auth - arguments:arguments - session:multiFactorSession - factorInfo:multiFactorInfo]; + FLTIdTokenChannelStreamHandler *handler = + [[FLTIdTokenChannelStreamHandler alloc] initWithAuth:auth]; [channel setStreamHandler:handler]; [_eventChannels setObject:channel forKey:name]; [_streamHandlers setObject:handler forKey:name]; - result.success(name); -#endif + completion(name, nil); } -#pragma mark - Utilities - -- (void)storeAuthCredentialIfPresent:(NSError *)error { - if ([error userInfo][FIRAuthErrorUserInfoUpdatedCredentialKey] != nil) { - FIRAuthCredential *authCredential = [error userInfo][FIRAuthErrorUserInfoUpdatedCredentialKey]; - // We temporarily store the non-serializable credential so the - // Dart API can consume these at a later time. - NSNumber *authCredentialHash = @([authCredential hash]); - _credentials[authCredentialHash] = authCredential; +- (void)sendPasswordResetEmailApp:(nonnull PigeonFirebaseApp *)app + email:(nonnull NSString *)email + actionCodeSettings:(nullable PigeonActionCodeSettings *)actionCodeSettings + completion:(nonnull void (^)(FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + if (actionCodeSettings != nil) { + FIRActionCodeSettings *settings = [PigeonParser parseActionCodeSettings:actionCodeSettings]; + [auth sendPasswordResetWithEmail:email + actionCodeSettings:settings + completion:^(NSError *_Nullable error) { + if (error != nil) { + completion([FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + completion(nil); + } + }]; + } else { + [auth sendPasswordResetWithEmail:email + completion:^(NSError *_Nullable error) { + if (error != nil) { + completion([FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + completion(nil); + } + }]; } } -+ (NSDictionary *)getNSDictionaryFromNSError:(NSError *)error { - NSString *code = @"unknown"; - NSString *message = @"An unknown error has occurred."; +- (void)sendSignInLinkToEmailApp:(nonnull PigeonFirebaseApp *)app + email:(nonnull NSString *)email + actionCodeSettings:(nonnull PigeonActionCodeSettings *)actionCodeSettings + completion:(nonnull void (^)(FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + [auth sendSignInLinkToEmail:email + actionCodeSettings:[PigeonParser parseActionCodeSettings:actionCodeSettings] + completion:^(NSError *_Nullable error) { + if (error != nil) { + completion([FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + completion(nil); + } + }]; +} - if (error == nil) { - return @{ - kArgumentCode : code, - @"message" : message, - @"additionalData" : @{}, - }; - } +- (void)setLanguageCodeApp:(nonnull PigeonFirebaseApp *)app + languageCode:(nullable NSString *)languageCode + completion: + (nonnull void (^)(NSString *_Nullable, FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; - // code - if ([error userInfo][FIRAuthErrorUserInfoNameKey] != nil) { - // See [FIRAuthErrorCodeString] for list of codes. - // Codes are in the format "ERROR_SOME_NAME", converting below to the format - // required in Dart. ERROR_SOME_NAME -> SOME_NAME - NSString *firebaseErrorCode = [error userInfo][FIRAuthErrorUserInfoNameKey]; - code = [firebaseErrorCode stringByReplacingOccurrencesOfString:@"ERROR_" withString:@""]; - // SOME_NAME -> SOME-NAME - code = [code stringByReplacingOccurrencesOfString:@"_" withString:@"-"]; - // SOME-NAME -> some-name - code = [code lowercaseString]; + if (languageCode != nil && ![languageCode isEqual:[NSNull null]]) { + auth.languageCode = languageCode; + } else { + [auth useAppLanguage]; } - // message - if ([error userInfo][NSLocalizedDescriptionKey] != nil) { - message = [error userInfo][NSLocalizedDescriptionKey]; + completion(auth.languageCode, nil); +} + +- (void)setSettingsApp:(nonnull PigeonFirebaseApp *)app + settings:(nonnull PigeonFirebaseAuthSettings *)settings + completion:(nonnull void (^)(FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + + if (settings.userAccessGroup != nil) { + BOOL useUserAccessGroupSuccessful; + NSError *useUserAccessGroupErrorPtr; + useUserAccessGroupSuccessful = [auth useUserAccessGroup:settings.userAccessGroup + error:&useUserAccessGroupErrorPtr]; + if (!useUserAccessGroupSuccessful) { + completion([FLTFirebaseAuthPlugin convertToFlutterError:useUserAccessGroupErrorPtr]); + return; + } } - NSMutableDictionary *additionalData = [NSMutableDictionary dictionary]; - // additionalData.email - if ([error userInfo][FIRAuthErrorUserInfoEmailKey] != nil) { - additionalData[kArgumentEmail] = [error userInfo][FIRAuthErrorUserInfoEmailKey]; - } - // additionalData.authCredential - if ([error userInfo][FIRAuthErrorUserInfoUpdatedCredentialKey] != nil) { - FIRAuthCredential *authCredential = [error userInfo][FIRAuthErrorUserInfoUpdatedCredentialKey]; - additionalData[@"authCredential"] = - [FLTFirebaseAuthPlugin getNSDictionaryFromAuthCredential:authCredential]; +#if TARGET_OS_IPHONE + if ([settings.appVerificationDisabledForTesting boolValue]) { + auth.settings.appVerificationDisabledForTesting = settings.appVerificationDisabledForTesting; } +#else + NSLog(@"FIRAuthSettings.appVerificationDisabledForTesting is not supported " + @"on MacOS."); +#endif - // Manual message overrides to ensure messages/codes matche other platforms. - if ([message isEqual:@"The password must be 6 characters long or more."]) { - message = @"Password should be at least 6 characters"; - } + completion(nil); +} - return @{ - kArgumentCode : code, - @"message" : message, - @"additionalData" : additionalData, - }; +- (void)signInAnonymouslyApp:(nonnull PigeonFirebaseApp *)app + completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + [auth signInAnonymouslyWithCompletion:^(FIRAuthDataResult *authResult, NSError *error) { + if (error != nil) { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + completion([PigeonParser getPigeonUserCredentialFromAuthResult:authResult], nil); + } + }]; } -- (FIRAuth *_Nullable)getFIRAuthFromArguments:(NSDictionary *)arguments { - NSString *appNameDart = arguments[kAppName]; - NSString *tenantId = arguments[@"tenantId"]; - FIRApp *app = [FLTFirebasePlugin firebaseAppNamed:appNameDart]; - FIRAuth *auth = [FIRAuth authWithApp:app]; +- (void)signInWithCredentialApp:(nonnull PigeonFirebaseApp *)app + input:(nonnull NSDictionary *)input + completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + FIRAuthCredential *credential = [self getFIRAuthCredentialFromArguments:input app:app]; - if (tenantId != nil && ![tenantId isEqual:[NSNull null]]) { - auth.tenantID = tenantId; + if (credential == nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeInvalidCredential + message:kErrMsgInvalidCredential + details:nil]); + return; } - return auth; -} + [auth signInWithCredential:credential + completion:^(FIRAuthDataResult *authResult, NSError *error) { + if (error != nil) { + NSDictionary *userInfo = [error userInfo]; + NSError *underlyingError = [userInfo objectForKey:NSUnderlyingErrorKey]; -- (FIRAuth *_Nullable)getFIRAuthFromAppName:(NSString *)appNameDart { - FIRApp *app = [FLTFirebasePlugin firebaseAppNamed:appNameDart]; - FIRAuth *auth = [FIRAuth authWithApp:app]; + NSDictionary *firebaseDictionary = + underlyingError.userInfo[@"FIRAuthErrorUserInfoDeserializedResponseKey"]; - return auth; + if (firebaseDictionary != nil && firebaseDictionary[@"message"] != nil) { + // error from firebase-ios-sdk is buried in underlying + // error. + completion(nil, [FlutterError errorWithCode:firebaseDictionary[@"code"] + message:firebaseDictionary[@"message"] + details:nil]); + } else { + if (error.code == FIRAuthErrorCodeSecondFactorRequired) { + [self handleMultiFactorError:app completion:completion withError:error]; + } else if (error.code == FIRAuthErrorCodeInternalError) { + [self handleInternalError:completion withError:error]; + } else { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } + } + } else { + completion([PigeonParser getPigeonUserCredentialFromAuthResult:authResult], + nil); + } + }]; } -- (FIRActionCodeSettings *_Nullable)getFIRActionCodeSettingsFromArguments: - (NSDictionary *)arguments { - NSDictionary *actionCodeSettingsDictionary = arguments[kArgumentActionCodeSettings]; - if (actionCodeSettingsDictionary == nil || [actionCodeSettingsDictionary isEqual:[NSNull null]]) { - return nil; - } +- (void)signInWithCustomTokenApp:(nonnull PigeonFirebaseApp *)app + token:(nonnull NSString *)token + completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; - FIRActionCodeSettings *actionCodeSettings = [FIRActionCodeSettings new]; - NSDictionary *iOSSettings = actionCodeSettingsDictionary[@"iOS"]; - NSDictionary *androidSettings = actionCodeSettingsDictionary[@"android"]; + [auth signInWithCustomToken:token + completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) { + if (error != nil) { + if (error.code == FIRAuthErrorCodeSecondFactorRequired) { + [self handleMultiFactorError:app completion:completion withError:error]; + } else if (error.code == FIRAuthErrorCodeInternalError) { + [self handleInternalError:completion withError:error]; + } else { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } + } else { + completion([PigeonParser getPigeonUserCredentialFromAuthResult:authResult], + nil); + } + }]; +} - // URL - required - actionCodeSettings.URL = [NSURL URLWithString:actionCodeSettingsDictionary[@"url"]]; +- (void)signInWithEmailAndPasswordApp:(nonnull PigeonFirebaseApp *)app + email:(nonnull NSString *)email + password:(nonnull NSString *)password + completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + [auth signInWithEmail:email + password:password + completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) { + if (error != nil) { + if (error.code == FIRAuthErrorCodeSecondFactorRequired) { + [self handleMultiFactorError:app completion:completion withError:error]; + } else if (error.code == FIRAuthErrorCodeInternalError) { + [self handleInternalError:completion withError:error]; + } else { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } + } else { + completion([PigeonParser getPigeonUserCredentialFromAuthResult:authResult], nil); + } + }]; +} - // Dynamic Link Domain - optional - if (actionCodeSettingsDictionary[@"dynamicLinkDomain"] != nil && - ![actionCodeSettingsDictionary[@"dynamicLinkDomain"] isEqual:[NSNull null]]) { - actionCodeSettings.dynamicLinkDomain = actionCodeSettingsDictionary[@"dynamicLinkDomain"]; - } +- (void)signInWithEmailLinkApp:(nonnull PigeonFirebaseApp *)app + email:(nonnull NSString *)email + emailLink:(nonnull NSString *)emailLink + completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + [auth signInWithEmail:email + link:emailLink + completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) { + if (error != nil) { + if (error.code == FIRAuthErrorCodeSecondFactorRequired) { + [self handleMultiFactorError:app completion:completion withError:error]; + } else if (error.code == FIRAuthErrorCodeInternalError) { + [self handleInternalError:completion withError:error]; + } else { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } + } else { + completion([PigeonParser getPigeonUserCredentialFromAuthResult:authResult], nil); + } + }]; +} - // Handle code in app - optional - if (actionCodeSettingsDictionary[@"handleCodeInApp"] != nil && - ![actionCodeSettingsDictionary[@"handleCodeInApp"] isEqual:[NSNull null]]) { - actionCodeSettings.handleCodeInApp = - [actionCodeSettingsDictionary[@"handleCodeInApp"] boolValue]; - } +- (void)signInWithProviderApp:(nonnull PigeonFirebaseApp *)app + signInProvider:(nonnull PigeonSignInProvider *)signInProvider + completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; - // Android settings - optional - if (androidSettings != nil && ![androidSettings isEqual:[NSNull null]]) { - BOOL installIfNotAvailable = NO; - if (androidSettings[@"installApp"] != nil && - ![androidSettings[@"installApp"] isEqual:[NSNull null]]) { - installIfNotAvailable = [androidSettings[@"installApp"] boolValue]; - } - [actionCodeSettings setAndroidPackageName:androidSettings[@"packageName"] - installIfNotAvailable:installIfNotAvailable - minimumVersion:androidSettings[@"minimumVersion"]]; + if ([signInProvider.providerId isEqualToString:kSignInMethodApple]) { + self.signInWithAppleAuth = auth; + launchAppleSignInRequest(self, app, signInProvider, completion); + return; } - - // iOS settings - optional - if (iOSSettings != nil && ![iOSSettings isEqual:[NSNull null]]) { - if (iOSSettings[@"bundleId"] != nil && ![iOSSettings[@"bundleId"] isEqual:[NSNull null]]) { - [actionCodeSettings setIOSBundleID:iOSSettings[@"bundleId"]]; - } +#if TARGET_OS_OSX + NSLog(@"signInWithProvider is not supported on the " + @"MacOS platform."); + completion(nil, nil); +#else + self.authProvider = [FIROAuthProvider providerWithProviderID:signInProvider.providerId]; + NSArray *scopes = signInProvider.scopes; + if (scopes != nil) { + [self.authProvider setScopes:scopes]; + } + NSDictionary *customParameters = signInProvider.customParameters; + if (customParameters != nil) { + [self.authProvider setCustomParameters:customParameters]; } - return actionCodeSettings; + [self.authProvider + getCredentialWithUIDelegate:nil + completion:^(FIRAuthCredential *_Nullable credential, + NSError *_Nullable error) { + handleAppleAuthResult(self, app, auth, credential, error, completion); + }]; +#endif } -- (FIRAuthCredential *_Nullable)getFIRAuthCredentialFromArguments:(NSDictionary *)arguments { - NSDictionary *credentialDictionary = arguments[kArgumentCredential]; +- (void)signOutApp:(nonnull PigeonFirebaseApp *)app + completion:(nonnull void (^)(FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; - // If the credential dictionary contains a token, it means a native one has - // been stored for later usage, so we'll attempt to retrieve it here. - if (credentialDictionary[kArgumentToken] != nil && - ![credentialDictionary[kArgumentToken] isEqual:[NSNull null]]) { - NSNumber *credentialHashCode = credentialDictionary[kArgumentToken]; - return _credentials[credentialHashCode]; + if (auth.currentUser == nil) { + completion(nil); + return; } - NSString *signInMethod = credentialDictionary[kArgumentSignInMethod]; - NSString *secret = credentialDictionary[kArgumentSecret] == [NSNull null] - ? nil - : credentialDictionary[kArgumentSecret]; - NSString *idToken = credentialDictionary[kArgumentIdToken] == [NSNull null] - ? nil - : credentialDictionary[kArgumentIdToken]; - NSString *accessToken = credentialDictionary[kArgumentAccessToken] == [NSNull null] - ? nil - : credentialDictionary[kArgumentAccessToken]; - NSString *rawNonce = credentialDictionary[kArgumentRawNonce] == [NSNull null] - ? nil - : credentialDictionary[kArgumentRawNonce]; + NSError *signOutErrorPtr; + BOOL signOutSuccessful = [auth signOut:&signOutErrorPtr]; - // Password Auth - if ([signInMethod isEqualToString:kSignInMethodPassword]) { - NSString *email = credentialDictionary[kArgumentEmail]; - return [FIREmailAuthProvider credentialWithEmail:email password:secret]; + if (!signOutSuccessful) { + completion([FLTFirebaseAuthPlugin convertToFlutterError:signOutErrorPtr]); + } else { + completion(nil); } +} - // Email Link Auth - if ([signInMethod isEqualToString:kSignInMethodEmailLink]) { - NSString *email = credentialDictionary[kArgumentEmail]; - NSString *emailLink = credentialDictionary[kArgumentEmailLink]; - return [FIREmailAuthProvider credentialWithEmail:email link:emailLink]; - } +- (void)useEmulatorApp:(nonnull PigeonFirebaseApp *)app + host:(nonnull NSString *)host + port:(nonnull NSNumber *)port + completion:(nonnull void (^)(FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + [auth useEmulatorWithHost:host port:[port integerValue]]; + completion(nil); +} - // Facebook Auth - if ([signInMethod isEqualToString:kSignInMethodFacebook]) { - return [FIRFacebookAuthProvider credentialWithAccessToken:accessToken]; - } +- (void)verifyPasswordResetCodeApp:(nonnull PigeonFirebaseApp *)app + code:(nonnull NSString *)code + completion:(nonnull void (^)(NSString *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; - // Google Auth - if ([signInMethod isEqualToString:kSignInMethodGoogle]) { - return [FIRGoogleAuthProvider credentialWithIDToken:idToken accessToken:accessToken]; - } + [auth verifyPasswordResetCode:code + completion:^(NSString *_Nullable email, NSError *_Nullable error) { + if (error != nil) { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + completion(email, nil); + } + }]; +} - // Twitter Auth - if ([signInMethod isEqualToString:kSignInMethodTwitter]) { - return [FIRTwitterAuthProvider credentialWithToken:accessToken secret:secret]; +- (void)verifyPhoneNumberApp:(nonnull PigeonFirebaseApp *)app + request:(nonnull PigeonVerifyPhoneNumberRequest *)request + completion: + (nonnull void (^)(NSString *_Nullable, FlutterError *_Nullable))completion { +#if TARGET_OS_OSX + NSLog(@"The Firebase Phone Authentication provider is not supported on the " + @"MacOS platform."); + completion(nil, nil); +#else + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + + NSString *name = [NSString + stringWithFormat:@"%@/phone/%@", kFLTFirebaseAuthChannelName, [NSUUID UUID].UUIDString]; + FlutterEventChannel *channel = [FlutterEventChannel eventChannelWithName:name + binaryMessenger:_binaryMessenger]; + + NSString *multiFactorSessionId = request.multiFactorSessionId; + FIRMultiFactorSession *multiFactorSession = nil; + + if (multiFactorSessionId != nil) { + multiFactorSession = _multiFactorSessionMap[multiFactorSessionId]; } - // GitHub Auth - if ([signInMethod isEqualToString:kSignInMethodGithub]) { - return [FIRGitHubAuthProvider credentialWithToken:accessToken]; + NSString *multiFactorInfoId = request.multiFactorInfoId; + + FIRPhoneMultiFactorInfo *multiFactorInfo = nil; + if (multiFactorInfoId != nil) { + for (NSString *resolverId in _multiFactorResolverMap) { + for (FIRMultiFactorInfo *info in _multiFactorResolverMap[resolverId].hints) { + if ([info.UID isEqualToString:multiFactorInfoId] && + [info class] == [FIRPhoneMultiFactorInfo class]) { + multiFactorInfo = (FIRPhoneMultiFactorInfo *)info; + break; + } + } + } } - // Phone Auth - Only supported on iOS - if ([signInMethod isEqualToString:kSignInMethodPhone]) { -#if TARGET_OS_IPHONE - NSString *verificationId = credentialDictionary[kArgumentVerificationId]; - NSString *smsCode = credentialDictionary[kArgumentSmsCode]; - return [[FIRPhoneAuthProvider providerWithAuth:[self getFIRAuthFromArguments:arguments]] - credentialWithVerificationID:verificationId - verificationCode:smsCode]; +#if TARGET_OS_OSX + FLTPhoneNumberVerificationStreamHandler *handler = + [[FLTPhoneNumberVerificationStreamHandler alloc] initWithAuth:auth]; #else - NSLog(@"The Firebase Phone Authentication provider is not supported on the " - @"MacOS platform."); - return nil; + FLTPhoneNumberVerificationStreamHandler *handler = + [[FLTPhoneNumberVerificationStreamHandler alloc] initWithAuth:auth + request:request + session:multiFactorSession + factorInfo:multiFactorInfo]; #endif - } - // OAuth - if ([signInMethod isEqualToString:kSignInMethodOAuth]) { - NSString *providerId = credentialDictionary[kArgumentProviderId]; - return [FIROAuthProvider credentialWithProviderID:providerId - IDToken:idToken - rawNonce:rawNonce - accessToken:accessToken]; - } + [channel setStreamHandler:handler]; - NSLog(@"Support for an auth provider with identifier '%@' is not implemented.", signInMethod); - return nil; -} + [_eventChannels setObject:channel forKey:name]; + [_streamHandlers setObject:handler forKey:name]; -- (NSDictionary *)getNSDictionaryFromAuthResult:(FIRAuthDataResult *)authResult { - return @{ - @"additionalUserInfo" : - [self getNSDictionaryFromAdditionalUserInfo:authResult.additionalUserInfo], - @"authCredential" : - [FLTFirebaseAuthPlugin getNSDictionaryFromAuthCredential:authResult.credential], - @"user" : [FLTFirebaseAuthPlugin getNSDictionaryFromUser:authResult.user], - }; + completion(name, nil); +#endif } -- (id)getNSDictionaryFromAdditionalUserInfo:(FIRAdditionalUserInfo *)additionalUserInfo { - if (additionalUserInfo == nil) { - return [NSNull null]; +- (void)deleteApp:(nonnull PigeonFirebaseApp *)app + completion:(nonnull void (^)(FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + FIRUser *currentUser = auth.currentUser; + if (currentUser == nil) { + completion([FlutterError errorWithCode:kErrCodeNoCurrentUser + message:kErrMsgNoCurrentUser + details:nil]); + return; } - return @{ - @"isNewUser" : @(additionalUserInfo.newUser), - @"profile" : (id)additionalUserInfo.profile ?: [NSNull null], - kArgumentProviderId : (id)additionalUserInfo.providerID ?: [NSNull null], - @"username" : (id)additionalUserInfo.username ?: [NSNull null], - }; + [currentUser deleteWithCompletion:^(NSError *_Nullable error) { + if (error != nil) { + completion([FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + completion(nil); + } + }]; } -+ (id)getNSDictionaryFromAuthCredential:(FIRAuthCredential *)authCredential { - if (authCredential == nil) { - return [NSNull null]; +- (void)getIdTokenApp:(nonnull PigeonFirebaseApp *)app + forceRefresh:(nonnull NSNumber *)forceRefresh + completion:(nonnull void (^)(PigeonIdTokenResult *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + FIRUser *currentUser = auth.currentUser; + if (currentUser == nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeNoCurrentUser + message:kErrMsgNoCurrentUser + details:nil]); + return; } - NSString *accessToken = nil; - if ([authCredential isKindOfClass:[FIROAuthCredential class]]) { - if (((FIROAuthCredential *)authCredential).accessToken != nil) { - accessToken = ((FIROAuthCredential *)authCredential).accessToken; - } else if (((FIROAuthCredential *)authCredential).IDToken != nil) { - // For Sign In With Apple, the token is stored in IDToken - accessToken = ((FIROAuthCredential *)authCredential).IDToken; - } - } + [currentUser + getIDTokenResultForcingRefresh:forceRefresh + completion:^(FIRAuthTokenResult *tokenResult, NSError *error) { + if (error != nil) { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + return; + } - return @{ - kArgumentProviderId : authCredential.provider, - // Note: "signInMethod" does not exist on iOS SDK, so using provider - // instead. - kArgumentSignInMethod : authCredential.provider, - kArgumentToken : @([authCredential hash]), - kArgumentAccessToken : accessToken ?: [NSNull null], - }; + completion([PigeonParser parseIdTokenResult:tokenResult], nil); + }]; } -+ (NSDictionary *)getNSDictionaryFromUserInfo:(id)userInfo { - NSString *photoURL = nil; - if (userInfo.photoURL != nil) { - photoURL = userInfo.photoURL.absoluteString; - if ([photoURL length] == 0) photoURL = nil; +- (void)linkWithCredentialApp:(nonnull PigeonFirebaseApp *)app + input:(nonnull NSDictionary *)input + completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + FIRUser *currentUser = auth.currentUser; + if (currentUser == nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeNoCurrentUser + message:kErrMsgNoCurrentUser + details:nil]); + return; } - return @{ - kArgumentProviderId : userInfo.providerID, - @"displayName" : (id)userInfo.displayName ?: [NSNull null], - @"uid" : (id)userInfo.uid ?: [NSNull null], - @"photoURL" : (id)photoURL ?: [NSNull null], - kArgumentEmail : (id)userInfo.email ?: [NSNull null], - @"phoneNumber" : (id)userInfo.phoneNumber ?: [NSNull null], - }; -} - -+ (NSMutableDictionary *)getNSDictionaryFromUser:(FIRUser *)user { - // FIRUser inherits from FIRUserInfo, so we can re-use - // `getNSDictionaryFromUserInfo` method. - NSMutableDictionary *userData = [[self getNSDictionaryFromUserInfo:user] mutableCopy]; - NSMutableDictionary *metadata = [NSMutableDictionary dictionary]; - - // metadata.creationTimestamp as milliseconds - long creationDate = (long)([user.metadata.creationDate timeIntervalSince1970] * 1000); - metadata[@"creationTime"] = @(creationDate); - - // metadata.lastSignInTimestamp as milliseconds - long lastSignInDate = (long)([user.metadata.lastSignInDate timeIntervalSince1970] * 1000); - metadata[@"lastSignInTime"] = @(lastSignInDate); - - // metadata - userData[@"metadata"] = metadata; - // providerData - NSMutableArray *> *providerData = - [NSMutableArray arrayWithCapacity:user.providerData.count]; - for (id userInfo in user.providerData) { - [providerData addObject:[FLTFirebaseAuthPlugin getNSDictionaryFromUserInfo:userInfo]]; + FIRAuthCredential *credential = [self getFIRAuthCredentialFromArguments:input app:app]; + if (credential == nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeInvalidCredential + message:kErrMsgInvalidCredential + details:nil]); + return; } - userData[@"providerData"] = providerData; - userData[@"isAnonymous"] = @(user.isAnonymous); - userData[@"emailVerified"] = @(user.isEmailVerified); + [currentUser + linkWithCredential:credential + completion:^(FIRAuthDataResult *authResult, NSError *error) { + if (error != nil) { + if (error.code == FIRAuthErrorCodeSecondFactorRequired) { + [self handleMultiFactorError:app completion:completion withError:error]; + } else { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } + } else { + completion([PigeonParser getPigeonUserCredentialFromAuthResult:authResult], nil); + } + }]; +} - if (user.tenantID != nil) { - userData[@"tenantId"] = user.tenantID; - } else { - userData[@"tenantId"] = [NSNull null]; +- (void)linkWithProviderApp:(nonnull PigeonFirebaseApp *)app + signInProvider:(nonnull PigeonSignInProvider *)signInProvider + completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + FIRUser *currentUser = auth.currentUser; + if (currentUser == nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeNoCurrentUser + message:kErrMsgNoCurrentUser + details:nil]); + return; } - // native does not provide refresh tokens - userData[@"refreshToken"] = @""; - return userData; -} - -- (void)ensureAPNSTokenSetting { -#if !TARGET_OS_OSX - FIRApp *defaultApp = [FIRApp defaultApp]; - if (defaultApp) { - if ([FIRAuth auth].APNSToken == nil && _apnsToken != nil) { - [[FIRAuth auth] setAPNSToken:_apnsToken type:FIRAuthAPNSTokenTypeUnknown]; - _apnsToken = nil; - } + if ([signInProvider.providerId isEqualToString:kSignInMethodApple]) { + self.linkWithAppleUser = currentUser; + launchAppleSignInRequest(self, app, signInProvider, completion); + return; + } +#if TARGET_OS_OSX + NSLog(@"linkWithProvider is not supported on the " + @"MacOS platform."); + completion(nil, nil); +#else + self.authProvider = [FIROAuthProvider providerWithProviderID:signInProvider.providerId]; + NSArray *scopes = signInProvider.scopes; + if (scopes != nil) { + [self.authProvider setScopes:scopes]; + } + NSDictionary *customParameters = signInProvider.customParameters; + if (customParameters != nil) { + [self.authProvider setCustomParameters:customParameters]; } + + [currentUser + linkWithProvider:self.authProvider + UIDelegate:nil + completion:^(FIRAuthDataResult *authResult, NSError *error) { + handleAppleAuthResult(self, app, auth, authResult.credential, error, completion); + }]; #endif } -#if TARGET_OS_IPHONE -- (FIRMultiFactor *)getAppMultiFactor:(nonnull NSString *)appName { - FIRAuth *auth = [self getFIRAuthFromAppName:appName]; +- (void)reauthenticateWithCredentialApp:(nonnull PigeonFirebaseApp *)app + input:(nonnull NSDictionary *)input + completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; FIRUser *currentUser = auth.currentUser; - return currentUser.multiFactor; -} - -- (void)enrollPhoneAppName:(nonnull NSString *)appName - assertion:(nonnull PigeonPhoneMultiFactorAssertion *)assertion - displayName:(nullable NSString *)displayName - completion:(nonnull void (^)(FlutterError *_Nullable))completion { - FIRMultiFactor *multiFactor = [self getAppMultiFactor:appName]; - - FIRPhoneAuthCredential *credential = - [[FIRPhoneAuthProvider providerWithAuth:[self getFIRAuthFromAppName:appName]] - credentialWithVerificationID:[assertion verificationId] - verificationCode:[assertion verificationCode]]; + if (currentUser == nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeNoCurrentUser + message:kErrMsgNoCurrentUser + details:nil]); + return; + } - FIRMultiFactorAssertion *multiFactorAssertion = - [FIRPhoneMultiFactorGenerator assertionWithCredential:credential]; + FIRAuthCredential *credential = [self getFIRAuthCredentialFromArguments:input app:app]; + if (credential == nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeInvalidCredential + message:kErrMsgInvalidCredential + details:nil]); + return; + } - [multiFactor enrollWithAssertion:multiFactorAssertion - displayName:displayName - completion:^(NSError *_Nullable error) { - if (error == nil) { - completion(nil); + [currentUser + reauthenticateWithCredential:credential + completion:^(FIRAuthDataResult *authResult, NSError *error) { + if (error != nil) { + if (error.code == FIRAuthErrorCodeSecondFactorRequired) { + [self handleMultiFactorError:app + completion:completion + withError:error]; + } else { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } } else { - completion([FlutterError errorWithCode:@"enroll-failed" - message:error.localizedDescription - details:nil]); + completion( + [PigeonParser getPigeonUserCredentialFromAuthResult:authResult], + nil); } }]; } -- (void)getEnrolledFactorsAppName:(nonnull NSString *)appName - completion:(nonnull void (^)(NSArray *_Nullable, - FlutterError *_Nullable))completion { - FIRMultiFactor *multiFactor = [self getAppMultiFactor:appName]; +- (void)reauthenticateWithProviderApp:(nonnull PigeonFirebaseApp *)app + signInProvider:(nonnull PigeonSignInProvider *)signInProvider + completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + FIRUser *currentUser = auth.currentUser; + if (currentUser == nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeNoCurrentUser + message:kErrMsgNoCurrentUser + details:nil]); + return; + } - NSArray *enrolledFactors = [multiFactor enrolledFactors]; + if ([signInProvider.providerId isEqualToString:kSignInMethodApple]) { + self.isReauthenticatingWithApple = YES; + launchAppleSignInRequest(self, app, signInProvider, completion); + return; + } +#if TARGET_OS_OSX + NSLog(@"reauthenticateWithProvider is not supported on the " + @"MacOS platform."); + completion(nil, nil); +#else + self.authProvider = [FIROAuthProvider providerWithProviderID:signInProvider.providerId]; + NSArray *scopes = signInProvider.scopes; + if (scopes != nil) { + [self.authProvider setScopes:scopes]; + } + NSDictionary *customParameters = signInProvider.customParameters; + if (customParameters != nil) { + [self.authProvider setCustomParameters:customParameters]; + } - NSMutableArray *results = [NSMutableArray array]; + [currentUser reauthenticateWithProvider:self.authProvider + UIDelegate:nil + completion:^(FIRAuthDataResult *authResult, NSError *error) { + handleAppleAuthResult(self, app, auth, authResult.credential, + error, completion); + }]; +#endif +} - for (FIRMultiFactorInfo *multiFactorInfo in enrolledFactors) { - NSString *phoneNumber; - if ([multiFactorInfo class] == [FIRPhoneMultiFactorInfo class]) { - FIRPhoneMultiFactorInfo *phoneFactorInfo = (FIRPhoneMultiFactorInfo *)multiFactorInfo; - phoneNumber = phoneFactorInfo.phoneNumber; +- (void)reloadApp:(nonnull PigeonFirebaseApp *)app + completion: + (nonnull void (^)(PigeonUserDetails *_Nullable, FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + FIRUser *currentUser = auth.currentUser; + if (currentUser == nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeNoCurrentUser + message:kErrMsgNoCurrentUser + details:nil]); + return; + } + + [currentUser reloadWithCompletion:^(NSError *_Nullable error) { + if (error != nil) { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + completion([PigeonParser getPigeonDetails:auth.currentUser], nil); } + }]; +} - [results - addObject:[PigeonMultiFactorInfo - makeWithDisplayName:multiFactorInfo.displayName - enrollmentTimestamp:[NSNumber numberWithDouble:multiFactorInfo.enrollmentDate - .timeIntervalSince1970] - factorId:multiFactorInfo.factorID - uid:multiFactorInfo.UID - phoneNumber:phoneNumber]]; +- (void)sendEmailVerificationApp:(nonnull PigeonFirebaseApp *)app + actionCodeSettings:(nullable PigeonActionCodeSettings *)actionCodeSettings + completion:(nonnull void (^)(FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + FIRUser *currentUser = auth.currentUser; + if (currentUser == nil) { + completion([FlutterError errorWithCode:kErrCodeNoCurrentUser + message:kErrMsgNoCurrentUser + details:nil]); + return; } - completion(results, nil); + [currentUser + sendEmailVerificationWithActionCodeSettings:[PigeonParser + parseActionCodeSettings:actionCodeSettings] + + completion:^(NSError *_Nullable error) { + if (error != nil) { + completion( + [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + completion(nil); + } + }]; +} + +- (void)unlinkApp:(nonnull PigeonFirebaseApp *)app + providerId:(nonnull NSString *)providerId + completion: + (nonnull void (^)(PigeonUserCredential *_Nullable, FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + FIRUser *currentUser = auth.currentUser; + if (currentUser == nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeNoCurrentUser + message:kErrMsgNoCurrentUser + details:nil]); + return; + } + + [currentUser unlinkFromProvider:providerId + completion:^(FIRUser *_Nullable user, NSError *_Nullable error) { + if (error != nil) { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + completion([PigeonParser getPigeonUserCredentialFromFIRUser:user], nil); + } + }]; } -- (void)getSessionAppName:(nonnull NSString *)appName - completion:(nonnull void (^)(PigeonMultiFactorSession *_Nullable, +- (void)updateEmailApp:(nonnull PigeonFirebaseApp *)app + newEmail:(nonnull NSString *)newEmail + completion:(nonnull void (^)(PigeonUserDetails *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + FIRUser *currentUser = auth.currentUser; + if (currentUser == nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeNoCurrentUser + message:kErrMsgNoCurrentUser + details:nil]); + return; + } + + [currentUser updateEmail:newEmail + completion:^(NSError *_Nullable error) { + if (error != nil) { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + [currentUser reloadWithCompletion:^(NSError *_Nullable reloadError) { + if (reloadError != nil) { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:reloadError]); + } else { + completion([PigeonParser getPigeonDetails:auth.currentUser], nil); + } + }]; + } + }]; +} + +- (void)updatePasswordApp:(nonnull PigeonFirebaseApp *)app + newPassword:(nonnull NSString *)newPassword + completion:(nonnull void (^)(PigeonUserDetails *_Nullable, FlutterError *_Nullable))completion { - FIRMultiFactor *multiFactor = [self getAppMultiFactor:appName]; - [multiFactor getSessionWithCompletion:^(FIRMultiFactorSession *_Nullable session, - NSError *_Nullable error) { - NSString *UUID = [[NSUUID UUID] UUIDString]; - self->_multiFactorSessionMap[UUID] = session; + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + FIRUser *currentUser = auth.currentUser; + if (currentUser == nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeNoCurrentUser + message:kErrMsgNoCurrentUser + details:nil]); + return; + } - PigeonMultiFactorSession *pigeonSession = [PigeonMultiFactorSession makeWithId:UUID]; - completion(pigeonSession, nil); - }]; + [currentUser + updatePassword:newPassword + completion:^(NSError *_Nullable error) { + if (error != nil) { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + [currentUser reloadWithCompletion:^(NSError *_Nullable reloadError) { + if (reloadError != nil) { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:reloadError]); + } else { + completion([PigeonParser getPigeonDetails:auth.currentUser], nil); + } + }]; + } + }]; } -- (void)unenrollAppName:(nonnull NSString *)appName - factorUid:(nullable NSString *)factorUid - completion:(nonnull void (^)(FlutterError *_Nullable))completion { - FIRMultiFactor *multiFactor = [self getAppMultiFactor:appName]; - [multiFactor unenrollWithFactorUID:factorUid - completion:^(NSError *_Nullable error) { - if (error == nil) { - completion(nil); - } else { - completion([FlutterError errorWithCode:@"unenroll-failed" - message:error.localizedDescription - details:nil]); - } - }]; +- (void)updatePhoneNumberApp:(nonnull PigeonFirebaseApp *)app + input:(nonnull NSDictionary *)input + completion:(nonnull void (^)(PigeonUserDetails *_Nullable, + FlutterError *_Nullable))completion { +#if TARGET_OS_IPHONE + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + FIRUser *currentUser = auth.currentUser; + if (currentUser == nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeNoCurrentUser + message:kErrMsgNoCurrentUser + details:nil]); + return; + } + + FIRAuthCredential *credential = [self getFIRAuthCredentialFromArguments:input app:app]; + if (credential == nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeInvalidCredential + message:kErrMsgInvalidCredential + details:nil]); + return; + } + + [currentUser + updatePhoneNumberCredential:(FIRPhoneAuthCredential *)credential + completion:^(NSError *_Nullable error) { + if (error != nil) { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + [currentUser reloadWithCompletion:^(NSError *_Nullable reloadError) { + if (reloadError != nil) { + completion( + nil, [FLTFirebaseAuthPlugin convertToFlutterError:reloadError]); + } else { + completion([PigeonParser getPigeonDetails:auth.currentUser], nil); + } + }]; + } + }]; +#else + NSLog(@"Updating a users phone number via Firebase Authentication is only " + @"supported on the iOS " + @"platform."); + completion(nil, nil); +#endif } -- (void)resolveSignInResolverId:(nonnull NSString *)resolverId - assertion:(nonnull PigeonPhoneMultiFactorAssertion *)assertion - completion:(nonnull void (^)(NSDictionary *_Nullable, - FlutterError *_Nullable))completion { - FIRMultiFactorResolver *resolver = _multiFactorResolverMap[resolverId]; +- (void)updateProfileApp:(nonnull PigeonFirebaseApp *)app + profile:(nonnull PigeonUserProfile *)profile + completion:(nonnull void (^)(PigeonUserDetails *_Nullable, + FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + FIRUser *currentUser = auth.currentUser; + if (currentUser == nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeNoCurrentUser + message:kErrMsgNoCurrentUser + details:nil]); + return; + } - FIRPhoneAuthCredential *credential = - [[FIRPhoneAuthProvider provider] credentialWithVerificationID:[assertion verificationId] - verificationCode:[assertion verificationCode]]; + FIRUserProfileChangeRequest *changeRequest = [currentUser profileChangeRequest]; - FIRMultiFactorAssertion *multiFactorAssertion = - [FIRPhoneMultiFactorGenerator assertionWithCredential:credential]; + if ([profile.displayNameChanged boolValue]) { + changeRequest.displayName = profile.displayName; + } - [resolver - resolveSignInWithAssertion:multiFactorAssertion - completion:^(FIRAuthDataResult *_Nullable authResult, - NSError *_Nullable error) { - if (error == nil) { - completion([self getNSDictionaryFromAuthResult:authResult], nil); - } else { - completion(nil, [FlutterError errorWithCode:@"resolve-signin-failed" - message:error.localizedDescription - details:nil]); - } - }]; + if ([profile.photoUrlChanged boolValue]) { + if (profile.photoUrl == nil) { + // We apparently cannot set photoURL to nil/NULL to remove it. + // Instead, setting it to empty string appears to work. + // When doing so, Dart will properly receive `null` anyway. + changeRequest.photoURL = [NSURL URLWithString:@""]; + } else { + changeRequest.photoURL = [NSURL URLWithString:profile.photoUrl]; + } + } + + [changeRequest commitChangesWithCompletion:^(NSError *error) { + if (error != nil) { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + [currentUser reloadWithCompletion:^(NSError *_Nullable reloadError) { + if (reloadError != nil) { + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:reloadError]); + } else { + completion([PigeonParser getPigeonDetails:auth.currentUser], nil); + } + }]; + } + }]; } -#endif +- (void)verifyBeforeUpdateEmailApp:(nonnull PigeonFirebaseApp *)app + newEmail:(nonnull NSString *)newEmail + actionCodeSettings:(nullable PigeonActionCodeSettings *)actionCodeSettings + completion:(nonnull void (^)(FlutterError *_Nullable))completion { + FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; + FIRUser *currentUser = auth.currentUser; + if (currentUser == nil) { + completion([FlutterError errorWithCode:kErrCodeNoCurrentUser + message:kErrMsgNoCurrentUser + details:nil]); + return; + } -- (nonnull ASPresentationAnchor)presentationAnchorForAuthorizationController: - (nonnull ASAuthorizationController *)controller API_AVAILABLE(macos(10.15), ios(13.0)) { -#if TARGET_OS_OSX - return [[NSApplication sharedApplication] keyWindow]; -#else - return [[UIApplication sharedApplication] keyWindow]; -#endif + [currentUser + sendEmailVerificationBeforeUpdatingEmail:newEmail + actionCodeSettings:[PigeonParser + parseActionCodeSettings:actionCodeSettings] + completion:^(NSError *error) { + if (error != nil) { + completion( + [FLTFirebaseAuthPlugin convertToFlutterError:error]); + } else { + completion(nil); + } + }]; } @end diff --git a/packages/firebase_auth/firebase_auth/ios/Classes/FLTIdTokenChannelStreamHandler.m b/packages/firebase_auth/firebase_auth/ios/Classes/FLTIdTokenChannelStreamHandler.m index b29ecbdcf3cf..7dccca9a7531 100644 --- a/packages/firebase_auth/firebase_auth/ios/Classes/FLTIdTokenChannelStreamHandler.m +++ b/packages/firebase_auth/firebase_auth/ios/Classes/FLTIdTokenChannelStreamHandler.m @@ -29,7 +29,7 @@ - (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSin } if (user) { - events(@{@"user" : [FLTFirebaseAuthPlugin getNSDictionaryFromUser:user]}); + events(@{@"user" : [[PigeonParser getPigeonDetails:user] toList]}); } else { events(@{@"user" : [NSNull null]}); } diff --git a/packages/firebase_auth/firebase_auth/ios/Classes/FLTPhoneNumberVerificationStreamHandler.m b/packages/firebase_auth/firebase_auth/ios/Classes/FLTPhoneNumberVerificationStreamHandler.m index 68ee7c404d7d..b9bc7076e426 100644 --- a/packages/firebase_auth/firebase_auth/ios/Classes/FLTPhoneNumberVerificationStreamHandler.m +++ b/packages/firebase_auth/firebase_auth/ios/Classes/FLTPhoneNumberVerificationStreamHandler.m @@ -16,24 +16,23 @@ @implementation FLTPhoneNumberVerificationStreamHandler { } #if TARGET_OS_OSX -- (instancetype)initWithAuth:(id)auth arguments:(NSDictionary *)arguments { +- (instancetype)initWithAuth:(id)auth request:(PigeonVerifyPhoneNumberRequest *)request { self = [super init]; if (self) { _auth = auth; - _phoneNumber = arguments[@"phoneNumber"]; + _phoneNumber = request.phoneNumber; } return self; } - #else - (instancetype)initWithAuth:(id)auth - arguments:(NSDictionary *)arguments + request:(PigeonVerifyPhoneNumberRequest *)request session:(FIRMultiFactorSession *)session factorInfo:(FIRPhoneMultiFactorInfo *)factorInfo { self = [super init]; if (self) { _auth = auth; - _phoneNumber = arguments[@"phoneNumber"]; + _phoneNumber = request.phoneNumber; _session = session; _factorInfo = factorInfo; } @@ -45,12 +44,13 @@ - (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSin #if TARGET_OS_IPHONE id completer = ^(NSString *verificationID, NSError *error) { if (error != nil) { - NSDictionary *errorDetails = [FLTFirebaseAuthPlugin getNSDictionaryFromNSError:error]; + FlutterError *errorDetails = [FLTFirebaseAuthPlugin convertToFlutterError:error]; events(@{ @"name" : @"Auth#phoneVerificationFailed", @"error" : @{ - @"message" : errorDetails[@"message"], - @"details" : errorDetails, + @"code" : errorDetails.code, + @"message" : errorDetails.message, + @"details" : errorDetails.details, } }); } else { diff --git a/packages/firebase_auth/firebase_auth/ios/Classes/PigeonParser.m b/packages/firebase_auth/firebase_auth/ios/Classes/PigeonParser.m new file mode 100644 index 000000000000..2c868d1ad006 --- /dev/null +++ b/packages/firebase_auth/firebase_auth/ios/Classes/PigeonParser.m @@ -0,0 +1,166 @@ +// Copyright 2023, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#import "PigeonParser.h" +#import + +@implementation PigeonParser + ++ (PigeonUserCredential *)getPigeonUserCredentialFromAuthResult: + (nonnull FIRAuthDataResult *)authResult { + return [PigeonUserCredential + makeWithUser:[self getPigeonDetails:authResult.user] + additionalUserInfo:[self getPigeonAdditionalUserInfo:authResult.additionalUserInfo] + credential:[self getPigeonAuthCredential:authResult.credential]]; +} + ++ (PigeonUserCredential *)getPigeonUserCredentialFromFIRUser:(nonnull FIRUser *)user { + return [PigeonUserCredential makeWithUser:[self getPigeonDetails:user] + additionalUserInfo:nil + credential:nil]; +} + ++ (PigeonUserDetails *)getPigeonDetails:(nonnull FIRUser *)user { + return [PigeonUserDetails makeWithUserInfo:[self getPigeonUserInfo:user] + providerData:[self getProviderData:user.providerData]]; +} + ++ (PigeonUserInfo *)getPigeonUserInfo:(nonnull FIRUser *)user { + return [PigeonUserInfo + makeWithUid:user.uid + email:user.email + displayName:user.displayName + photoUrl:(user.photoURL.absoluteString.length > 0) ? user.photoURL.absoluteString + : nil + phoneNumber:user.phoneNumber + isAnonymous:[NSNumber numberWithBool:user.isAnonymous] + isEmailVerified:[NSNumber numberWithBool:user.emailVerified] + providerId:user.providerID + tenantId:user.tenantID + refreshToken:user.refreshToken + creationTimestamp:@((long)([user.metadata.creationDate timeIntervalSince1970] * 1000)) + lastSignInTimestamp:@((long)([user.metadata.lastSignInDate timeIntervalSince1970] * 1000))]; +} + ++ (NSArray *> *)getProviderData: + (nonnull NSArray> *)providerData { + NSMutableArray *> *dataArray = + [NSMutableArray arrayWithCapacity:providerData.count]; + + for (id userInfo in providerData) { + NSDictionary *dataDict = @{ + @"providerId" : userInfo.providerID, + // Can be null on emulator + @"uid" : userInfo.uid ?: @"", + @"displayName" : userInfo.displayName ?: [NSNull null], + @"email" : userInfo.email ?: [NSNull null], + @"phoneNumber" : userInfo.phoneNumber ?: [NSNull null], + @"photoURL" : userInfo.photoURL.absoluteString ?: [NSNull null], + // isAnonymous is always false on in a providerData object (the user is not anonymous) + @"isAnonymous" : @NO, + // isEmailVerified is always true on in a providerData object (the email is verified by the + // provider) + @"isEmailVerified" : @YES, + }; + [dataArray addObject:dataDict]; + } + return [dataArray copy]; +} + ++ (PigeonAdditionalUserInfo *)getPigeonAdditionalUserInfo: + (nonnull FIRAdditionalUserInfo *)userInfo { + return [PigeonAdditionalUserInfo makeWithIsNewUser:[NSNumber numberWithBool:userInfo.isNewUser] + providerId:userInfo.providerID + username:userInfo.username + profile:userInfo.profile]; +} + ++ (PigeonAuthCredential *)getPigeonAuthCredential:(FIRAuthCredential *)authCredential { + if (authCredential == nil) { + return nil; + } + + NSString *accessToken = nil; + if ([authCredential isKindOfClass:[FIROAuthCredential class]]) { + if (((FIROAuthCredential *)authCredential).accessToken != nil) { + accessToken = ((FIROAuthCredential *)authCredential).accessToken; + } else if (((FIROAuthCredential *)authCredential).IDToken != nil) { + // For Sign In With Apple, the token is stored in IDToken + accessToken = ((FIROAuthCredential *)authCredential).IDToken; + } + } + + return [PigeonAuthCredential makeWithProviderId:authCredential.provider + signInMethod:authCredential.provider + nativeId:@([authCredential hash]) + accessToken:accessToken ?: nil]; +} + ++ (PigeonActionCodeInfo *_Nullable)parseActionCode:(nonnull FIRActionCodeInfo *)info { + PigeonActionCodeInfoData *data = [PigeonActionCodeInfoData makeWithEmail:info.email + previousEmail:info.previousEmail]; + + ActionCodeInfoOperation operation; + + if (info.operation == FIRActionCodeOperationPasswordReset) { + operation = ActionCodeInfoOperationPasswordReset; + } else if (info.operation == FIRActionCodeOperationVerifyEmail) { + operation = ActionCodeInfoOperationVerifyEmail; + } else if (info.operation == FIRActionCodeOperationRecoverEmail) { + operation = ActionCodeInfoOperationRecoverEmail; + } else if (info.operation == FIRActionCodeOperationEmailLink) { + operation = ActionCodeInfoOperationEmailSignIn; + } else if (info.operation == FIRActionCodeOperationVerifyAndChangeEmail) { + operation = ActionCodeInfoOperationVerifyAndChangeEmail; + } else if (info.operation == FIRActionCodeOperationRevertSecondFactorAddition) { + operation = ActionCodeInfoOperationRevertSecondFactorAddition; + } else { + operation = ActionCodeInfoOperationUnknown; + } + + return [PigeonActionCodeInfo makeWithOperation:operation data:data]; +} + ++ (FIRActionCodeSettings *_Nullable)parseActionCodeSettings: + (nullable PigeonActionCodeSettings *)settings { + if (settings == nil) { + return nil; + } + + FIRActionCodeSettings *codeSettings = [[FIRActionCodeSettings alloc] init]; + + if (settings.url != nil) { + codeSettings.URL = [NSURL URLWithString:settings.url]; + } + + if (settings.dynamicLinkDomain != nil) { + codeSettings.dynamicLinkDomain = settings.dynamicLinkDomain; + } + + if (settings.handleCodeInApp != nil) { + codeSettings.handleCodeInApp = [settings.handleCodeInApp boolValue]; + } + + if (settings.iOSBundleId != nil) { + codeSettings.iOSBundleID = settings.iOSBundleId; + } + + return codeSettings; +} + ++ (PigeonIdTokenResult *)parseIdTokenResult:(FIRAuthTokenResult *)tokenResult { + long expirationTimestamp = (long)[tokenResult.expirationDate timeIntervalSince1970] * 1000; + long authTimestamp = (long)[tokenResult.authDate timeIntervalSince1970] * 1000; + long issuedAtTimestamp = (long)[tokenResult.issuedAtDate timeIntervalSince1970] * 1000; + + return [PigeonIdTokenResult makeWithToken:tokenResult.token + expirationTimestamp:@(expirationTimestamp) + authTimestamp:@(authTimestamp) + issuedAtTimestamp:@(issuedAtTimestamp) + signInProvider:tokenResult.signInProvider + claims:tokenResult.claims + signInSecondFactor:tokenResult.signInSecondFactor]; +} + +@end diff --git a/packages/firebase_auth/firebase_auth/ios/Classes/Private/FLTAuthStateChannelStreamHandler.h b/packages/firebase_auth/firebase_auth/ios/Classes/Private/FLTAuthStateChannelStreamHandler.h index 35c388c8d891..3b0fbb9d9b66 100644 --- a/packages/firebase_auth/firebase_auth/ios/Classes/Private/FLTAuthStateChannelStreamHandler.h +++ b/packages/firebase_auth/firebase_auth/ios/Classes/Private/FLTAuthStateChannelStreamHandler.h @@ -13,6 +13,8 @@ #import #import +#import "CustomPigeonHeader.h" +#import "PigeonParser.h" NS_ASSUME_NONNULL_BEGIN diff --git a/packages/firebase_auth/firebase_auth/ios/Classes/Private/FLTIdTokenChannelStreamHandler.h b/packages/firebase_auth/firebase_auth/ios/Classes/Private/FLTIdTokenChannelStreamHandler.h index 4137ecb0acbd..0f118bec4033 100644 --- a/packages/firebase_auth/firebase_auth/ios/Classes/Private/FLTIdTokenChannelStreamHandler.h +++ b/packages/firebase_auth/firebase_auth/ios/Classes/Private/FLTIdTokenChannelStreamHandler.h @@ -11,6 +11,8 @@ #endif #import +#import "CustomPigeonHeader.h" +#import "PigeonParser.h" #import diff --git a/packages/firebase_auth/firebase_auth/ios/Classes/Private/FLTPhoneNumberVerificationStreamHandler.h b/packages/firebase_auth/firebase_auth/ios/Classes/Private/FLTPhoneNumberVerificationStreamHandler.h index 9b61df9b46ea..9035c800f4dd 100644 --- a/packages/firebase_auth/firebase_auth/ios/Classes/Private/FLTPhoneNumberVerificationStreamHandler.h +++ b/packages/firebase_auth/firebase_auth/ios/Classes/Private/FLTPhoneNumberVerificationStreamHandler.h @@ -11,6 +11,7 @@ #endif #import +#import "messages.g.h" #import @@ -22,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithAuth:(FIRAuth *)auth arguments:(NSDictionary *)arguments; #else - (instancetype)initWithAuth:(FIRAuth *)auth - arguments:(NSDictionary *)arguments + request:(PigeonVerifyPhoneNumberRequest *)request session:(FIRMultiFactorSession *)session factorInfo:(FIRPhoneMultiFactorInfo *)factorInfo; #endif diff --git a/packages/firebase_auth/firebase_auth/ios/Classes/Private/PigeonParser.h b/packages/firebase_auth/firebase_auth/ios/Classes/Private/PigeonParser.h new file mode 100644 index 000000000000..1751a3192fcb --- /dev/null +++ b/packages/firebase_auth/firebase_auth/ios/Classes/Private/PigeonParser.h @@ -0,0 +1,23 @@ +/* + * Copyright 2023, the Chromium project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#import +#import +#import "messages.g.h" + +@interface PigeonParser : NSObject + ++ (PigeonUserCredential *_Nullable)getPigeonUserCredentialFromAuthResult: + (nonnull FIRAuthDataResult *)authResult; ++ (PigeonUserDetails *_Nullable)getPigeonDetails:(nonnull FIRUser *)user; ++ (PigeonUserInfo *_Nullable)getPigeonUserInfo:(nonnull FIRUser *)user; ++ (PigeonActionCodeInfo *_Nullable)parseActionCode:(nonnull FIRActionCodeInfo *)info; ++ (FIRActionCodeSettings *_Nullable)parseActionCodeSettings: + (nullable PigeonActionCodeSettings *)settings; ++ (PigeonUserCredential *_Nullable)getPigeonUserCredentialFromFIRUser:(nonnull FIRUser *)user; ++ (PigeonIdTokenResult *)parseIdTokenResult:(FIRAuthTokenResult *)tokenResult; + +@end diff --git a/packages/firebase_auth/firebase_auth/ios/Classes/Public/CustomPigeonHeader.h b/packages/firebase_auth/firebase_auth/ios/Classes/Public/CustomPigeonHeader.h index 798ecfbffbed..f068d5268a78 100644 --- a/packages/firebase_auth/firebase_auth/ios/Classes/Public/CustomPigeonHeader.h +++ b/packages/firebase_auth/firebase_auth/ios/Classes/Public/CustomPigeonHeader.h @@ -4,5 +4,9 @@ #import "messages.g.h" @interface PigeonMultiFactorInfo (Map) -- (NSDictionary *)toMap; +- (NSDictionary *)toList; +@end + +@interface PigeonUserDetails (Map) +- (NSDictionary *)toList; @end diff --git a/packages/firebase_auth/firebase_auth/ios/Classes/Public/FLTFirebaseAuthPlugin.h b/packages/firebase_auth/firebase_auth/ios/Classes/Public/FLTFirebaseAuthPlugin.h index fa0221bbd10e..dd78270f9c6c 100644 --- a/packages/firebase_auth/firebase_auth/ios/Classes/Public/FLTFirebaseAuthPlugin.h +++ b/packages/firebase_auth/firebase_auth/ios/Classes/Public/FLTFirebaseAuthPlugin.h @@ -18,13 +18,14 @@ @interface FLTFirebaseAuthPlugin : FLTFirebasePlugin -+ (id)getNSDictionaryFromAuthCredential:(FIRAuthCredential *)authCredential; + (NSDictionary *)getNSDictionaryFromUserInfo:(id)userInfo; + (NSMutableDictionary *)getNSDictionaryFromUser:(FIRUser *)user; -+ (NSDictionary *)getNSDictionaryFromNSError:(NSError *)error; ++ (FlutterError *)convertToFlutterError:(NSError *)error; @end diff --git a/packages/firebase_auth/firebase_auth/ios/Classes/Public/messages.g.h b/packages/firebase_auth/firebase_auth/ios/Classes/Public/messages.g.h index dbe39ae7150f..1753ab0f3d31 100644 --- a/packages/firebase_auth/firebase_auth/ios/Classes/Public/messages.g.h +++ b/packages/firebase_auth/firebase_auth/ios/Classes/Public/messages.g.h @@ -1,6 +1,8 @@ -// Autogenerated from Pigeon (v3.2.3), do not edit directly. +// Autogenerated from Pigeon (v9.2.4), do not edit directly. // See also: https://pub.dev/packages/pigeon + #import + @protocol FlutterBinaryMessenger; @protocol FlutterMessageCodec; @class FlutterError; @@ -8,9 +10,42 @@ NS_ASSUME_NONNULL_BEGIN +/// The type of operation that generated the action code from calling +/// [checkActionCode]. +typedef NS_ENUM(NSUInteger, ActionCodeInfoOperation) { + /// Unknown operation. + ActionCodeInfoOperationUnknown = 0, + /// Password reset code generated via [sendPasswordResetEmail]. + ActionCodeInfoOperationPasswordReset = 1, + /// Email verification code generated via [User.sendEmailVerification]. + ActionCodeInfoOperationVerifyEmail = 2, + /// Email change revocation code generated via [User.updateEmail]. + ActionCodeInfoOperationRecoverEmail = 3, + /// Email sign in code generated via [sendSignInLinkToEmail]. + ActionCodeInfoOperationEmailSignIn = 4, + /// Verify and change email code generated via [User.verifyBeforeUpdateEmail]. + ActionCodeInfoOperationVerifyAndChangeEmail = 5, + /// Action code for reverting second factor addition. + ActionCodeInfoOperationRevertSecondFactorAddition = 6, +}; + @class PigeonMultiFactorSession; @class PigeonPhoneMultiFactorAssertion; @class PigeonMultiFactorInfo; +@class PigeonFirebaseApp; +@class PigeonActionCodeInfo; +@class PigeonActionCodeInfoData; +@class PigeonUserCredential; +@class PigeonAdditionalUserInfo; +@class PigeonAuthCredential; +@class PigeonUserInfo; +@class PigeonUserDetails; +@class PigeonActionCodeSettings; +@class PigeonFirebaseAuthSettings; +@class PigeonSignInProvider; +@class PigeonVerifyPhoneNumberRequest; +@class PigeonIdTokenResult; +@class PigeonUserProfile; @interface PigeonMultiFactorSession : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. @@ -43,23 +78,357 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, copy, nullable) NSString *phoneNumber; @end +@interface PigeonFirebaseApp : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithAppName:(NSString *)appName tenantId:(nullable NSString *)tenantId; +@property(nonatomic, copy) NSString *appName; +@property(nonatomic, copy, nullable) NSString *tenantId; +@end + +@interface PigeonActionCodeInfo : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithOperation:(ActionCodeInfoOperation)operation + data:(PigeonActionCodeInfoData *)data; +@property(nonatomic, assign) ActionCodeInfoOperation operation; +@property(nonatomic, strong) PigeonActionCodeInfoData *data; +@end + +@interface PigeonActionCodeInfoData : NSObject ++ (instancetype)makeWithEmail:(nullable NSString *)email + previousEmail:(nullable NSString *)previousEmail; +@property(nonatomic, copy, nullable) NSString *email; +@property(nonatomic, copy, nullable) NSString *previousEmail; +@end + +@interface PigeonUserCredential : NSObject ++ (instancetype)makeWithUser:(nullable PigeonUserDetails *)user + additionalUserInfo:(nullable PigeonAdditionalUserInfo *)additionalUserInfo + credential:(nullable PigeonAuthCredential *)credential; +@property(nonatomic, strong, nullable) PigeonUserDetails *user; +@property(nonatomic, strong, nullable) PigeonAdditionalUserInfo *additionalUserInfo; +@property(nonatomic, strong, nullable) PigeonAuthCredential *credential; +@end + +@interface PigeonAdditionalUserInfo : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithIsNewUser:(NSNumber *)isNewUser + providerId:(nullable NSString *)providerId + username:(nullable NSString *)username + profile:(nullable NSDictionary *)profile; +@property(nonatomic, strong) NSNumber *isNewUser; +@property(nonatomic, copy, nullable) NSString *providerId; +@property(nonatomic, copy, nullable) NSString *username; +@property(nonatomic, strong, nullable) NSDictionary *profile; +@end + +@interface PigeonAuthCredential : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithProviderId:(NSString *)providerId + signInMethod:(NSString *)signInMethod + nativeId:(NSNumber *)nativeId + accessToken:(nullable NSString *)accessToken; +@property(nonatomic, copy) NSString *providerId; +@property(nonatomic, copy) NSString *signInMethod; +@property(nonatomic, strong) NSNumber *nativeId; +@property(nonatomic, copy, nullable) NSString *accessToken; +@end + +@interface PigeonUserInfo : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithUid:(NSString *)uid + email:(nullable NSString *)email + displayName:(nullable NSString *)displayName + photoUrl:(nullable NSString *)photoUrl + phoneNumber:(nullable NSString *)phoneNumber + isAnonymous:(NSNumber *)isAnonymous + isEmailVerified:(NSNumber *)isEmailVerified + providerId:(nullable NSString *)providerId + tenantId:(nullable NSString *)tenantId + refreshToken:(nullable NSString *)refreshToken + creationTimestamp:(nullable NSNumber *)creationTimestamp + lastSignInTimestamp:(nullable NSNumber *)lastSignInTimestamp; +@property(nonatomic, copy) NSString *uid; +@property(nonatomic, copy, nullable) NSString *email; +@property(nonatomic, copy, nullable) NSString *displayName; +@property(nonatomic, copy, nullable) NSString *photoUrl; +@property(nonatomic, copy, nullable) NSString *phoneNumber; +@property(nonatomic, strong) NSNumber *isAnonymous; +@property(nonatomic, strong) NSNumber *isEmailVerified; +@property(nonatomic, copy, nullable) NSString *providerId; +@property(nonatomic, copy, nullable) NSString *tenantId; +@property(nonatomic, copy, nullable) NSString *refreshToken; +@property(nonatomic, strong, nullable) NSNumber *creationTimestamp; +@property(nonatomic, strong, nullable) NSNumber *lastSignInTimestamp; +@end + +@interface PigeonUserDetails : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithUserInfo:(PigeonUserInfo *)userInfo + providerData:(NSArray *> *)providerData; +@property(nonatomic, strong) PigeonUserInfo *userInfo; +@property(nonatomic, strong) NSArray *> *providerData; +@end + +@interface PigeonActionCodeSettings : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithUrl:(NSString *)url + dynamicLinkDomain:(nullable NSString *)dynamicLinkDomain + handleCodeInApp:(NSNumber *)handleCodeInApp + iOSBundleId:(nullable NSString *)iOSBundleId + androidPackageName:(nullable NSString *)androidPackageName + androidInstallApp:(NSNumber *)androidInstallApp + androidMinimumVersion:(nullable NSString *)androidMinimumVersion; +@property(nonatomic, copy) NSString *url; +@property(nonatomic, copy, nullable) NSString *dynamicLinkDomain; +@property(nonatomic, strong) NSNumber *handleCodeInApp; +@property(nonatomic, copy, nullable) NSString *iOSBundleId; +@property(nonatomic, copy, nullable) NSString *androidPackageName; +@property(nonatomic, strong) NSNumber *androidInstallApp; +@property(nonatomic, copy, nullable) NSString *androidMinimumVersion; +@end + +@interface PigeonFirebaseAuthSettings : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithAppVerificationDisabledForTesting: + (NSNumber *)appVerificationDisabledForTesting + userAccessGroup:(nullable NSString *)userAccessGroup + phoneNumber:(nullable NSString *)phoneNumber + smsCode:(nullable NSString *)smsCode + forceRecaptchaFlow:(nullable NSNumber *)forceRecaptchaFlow; +@property(nonatomic, strong) NSNumber *appVerificationDisabledForTesting; +@property(nonatomic, copy, nullable) NSString *userAccessGroup; +@property(nonatomic, copy, nullable) NSString *phoneNumber; +@property(nonatomic, copy, nullable) NSString *smsCode; +@property(nonatomic, strong, nullable) NSNumber *forceRecaptchaFlow; +@end + +@interface PigeonSignInProvider : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithProviderId:(NSString *)providerId + scopes:(nullable NSArray *)scopes + customParameters: + (nullable NSDictionary *)customParameters; +@property(nonatomic, copy) NSString *providerId; +@property(nonatomic, strong, nullable) NSArray *scopes; +@property(nonatomic, strong, nullable) NSDictionary *customParameters; +@end + +@interface PigeonVerifyPhoneNumberRequest : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithPhoneNumber:(nullable NSString *)phoneNumber + timeout:(NSNumber *)timeout + forceResendingToken:(nullable NSNumber *)forceResendingToken + autoRetrievedSmsCodeForTesting:(nullable NSString *)autoRetrievedSmsCodeForTesting + multiFactorInfoId:(nullable NSString *)multiFactorInfoId + multiFactorSessionId:(nullable NSString *)multiFactorSessionId; +@property(nonatomic, copy, nullable) NSString *phoneNumber; +@property(nonatomic, strong) NSNumber *timeout; +@property(nonatomic, strong, nullable) NSNumber *forceResendingToken; +@property(nonatomic, copy, nullable) NSString *autoRetrievedSmsCodeForTesting; +@property(nonatomic, copy, nullable) NSString *multiFactorInfoId; +@property(nonatomic, copy, nullable) NSString *multiFactorSessionId; +@end + +@interface PigeonIdTokenResult : NSObject ++ (instancetype)makeWithToken:(nullable NSString *)token + expirationTimestamp:(nullable NSNumber *)expirationTimestamp + authTimestamp:(nullable NSNumber *)authTimestamp + issuedAtTimestamp:(nullable NSNumber *)issuedAtTimestamp + signInProvider:(nullable NSString *)signInProvider + claims:(nullable NSDictionary *)claims + signInSecondFactor:(nullable NSString *)signInSecondFactor; +@property(nonatomic, copy, nullable) NSString *token; +@property(nonatomic, strong, nullable) NSNumber *expirationTimestamp; +@property(nonatomic, strong, nullable) NSNumber *authTimestamp; +@property(nonatomic, strong, nullable) NSNumber *issuedAtTimestamp; +@property(nonatomic, copy, nullable) NSString *signInProvider; +@property(nonatomic, strong, nullable) NSDictionary *claims; +@property(nonatomic, copy, nullable) NSString *signInSecondFactor; +@end + +@interface PigeonUserProfile : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithDisplayName:(nullable NSString *)displayName + photoUrl:(nullable NSString *)photoUrl + displayNameChanged:(NSNumber *)displayNameChanged + photoUrlChanged:(NSNumber *)photoUrlChanged; +@property(nonatomic, copy, nullable) NSString *displayName; +@property(nonatomic, copy, nullable) NSString *photoUrl; +@property(nonatomic, strong) NSNumber *displayNameChanged; +@property(nonatomic, strong) NSNumber *photoUrlChanged; +@end + +/// The codec used by FirebaseAuthHostApi. +NSObject *FirebaseAuthHostApiGetCodec(void); + +@protocol FirebaseAuthHostApi +- (void)registerIdTokenListenerApp:(PigeonFirebaseApp *)app + completion: + (void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; +- (void)registerAuthStateListenerApp:(PigeonFirebaseApp *)app + completion: + (void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; +- (void)useEmulatorApp:(PigeonFirebaseApp *)app + host:(NSString *)host + port:(NSNumber *)port + completion:(void (^)(FlutterError *_Nullable))completion; +- (void)applyActionCodeApp:(PigeonFirebaseApp *)app + code:(NSString *)code + completion:(void (^)(FlutterError *_Nullable))completion; +- (void)checkActionCodeApp:(PigeonFirebaseApp *)app + code:(NSString *)code + completion: + (void (^)(PigeonActionCodeInfo *_Nullable, FlutterError *_Nullable))completion; +- (void)confirmPasswordResetApp:(PigeonFirebaseApp *)app + code:(NSString *)code + newPassword:(NSString *)newPassword + completion:(void (^)(FlutterError *_Nullable))completion; +- (void)createUserWithEmailAndPasswordApp:(PigeonFirebaseApp *)app + email:(NSString *)email + password:(NSString *)password + completion:(void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion; +- (void)signInAnonymouslyApp:(PigeonFirebaseApp *)app + completion:(void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion; +- (void)signInWithCredentialApp:(PigeonFirebaseApp *)app + input:(NSDictionary *)input + completion:(void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion; +- (void)signInWithCustomTokenApp:(PigeonFirebaseApp *)app + token:(NSString *)token + completion:(void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion; +- (void)signInWithEmailAndPasswordApp:(PigeonFirebaseApp *)app + email:(NSString *)email + password:(NSString *)password + completion:(void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion; +- (void)signInWithEmailLinkApp:(PigeonFirebaseApp *)app + email:(NSString *)email + emailLink:(NSString *)emailLink + completion:(void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion; +- (void)signInWithProviderApp:(PigeonFirebaseApp *)app + signInProvider:(PigeonSignInProvider *)signInProvider + completion:(void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion; +- (void)signOutApp:(PigeonFirebaseApp *)app + completion:(void (^)(FlutterError *_Nullable))completion; +- (void)fetchSignInMethodsForEmailApp:(PigeonFirebaseApp *)app + email:(NSString *)email + completion:(void (^)(NSArray *_Nullable, + FlutterError *_Nullable))completion; +- (void)sendPasswordResetEmailApp:(PigeonFirebaseApp *)app + email:(NSString *)email + actionCodeSettings:(nullable PigeonActionCodeSettings *)actionCodeSettings + completion:(void (^)(FlutterError *_Nullable))completion; +- (void)sendSignInLinkToEmailApp:(PigeonFirebaseApp *)app + email:(NSString *)email + actionCodeSettings:(PigeonActionCodeSettings *)actionCodeSettings + completion:(void (^)(FlutterError *_Nullable))completion; +- (void)setLanguageCodeApp:(PigeonFirebaseApp *)app + languageCode:(nullable NSString *)languageCode + completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; +- (void)setSettingsApp:(PigeonFirebaseApp *)app + settings:(PigeonFirebaseAuthSettings *)settings + completion:(void (^)(FlutterError *_Nullable))completion; +- (void)verifyPasswordResetCodeApp:(PigeonFirebaseApp *)app + code:(NSString *)code + completion: + (void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; +- (void)verifyPhoneNumberApp:(PigeonFirebaseApp *)app + request:(PigeonVerifyPhoneNumberRequest *)request + completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; +@end + +extern void FirebaseAuthHostApiSetup(id binaryMessenger, + NSObject *_Nullable api); + +/// The codec used by FirebaseAuthUserHostApi. +NSObject *FirebaseAuthUserHostApiGetCodec(void); + +@protocol FirebaseAuthUserHostApi +- (void)deleteApp:(PigeonFirebaseApp *)app completion:(void (^)(FlutterError *_Nullable))completion; +- (void)getIdTokenApp:(PigeonFirebaseApp *)app + forceRefresh:(NSNumber *)forceRefresh + completion:(void (^)(PigeonIdTokenResult *_Nullable, FlutterError *_Nullable))completion; +- (void)linkWithCredentialApp:(PigeonFirebaseApp *)app + input:(NSDictionary *)input + completion:(void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion; +- (void)linkWithProviderApp:(PigeonFirebaseApp *)app + signInProvider:(PigeonSignInProvider *)signInProvider + completion: + (void (^)(PigeonUserCredential *_Nullable, FlutterError *_Nullable))completion; +- (void)reauthenticateWithCredentialApp:(PigeonFirebaseApp *)app + input:(NSDictionary *)input + completion:(void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion; +- (void)reauthenticateWithProviderApp:(PigeonFirebaseApp *)app + signInProvider:(PigeonSignInProvider *)signInProvider + completion:(void (^)(PigeonUserCredential *_Nullable, + FlutterError *_Nullable))completion; +- (void)reloadApp:(PigeonFirebaseApp *)app + completion:(void (^)(PigeonUserDetails *_Nullable, FlutterError *_Nullable))completion; +- (void)sendEmailVerificationApp:(PigeonFirebaseApp *)app + actionCodeSettings:(nullable PigeonActionCodeSettings *)actionCodeSettings + completion:(void (^)(FlutterError *_Nullable))completion; +- (void)unlinkApp:(PigeonFirebaseApp *)app + providerId:(NSString *)providerId + completion:(void (^)(PigeonUserCredential *_Nullable, FlutterError *_Nullable))completion; +- (void)updateEmailApp:(PigeonFirebaseApp *)app + newEmail:(NSString *)newEmail + completion:(void (^)(PigeonUserDetails *_Nullable, FlutterError *_Nullable))completion; +- (void)updatePasswordApp:(PigeonFirebaseApp *)app + newPassword:(NSString *)newPassword + completion: + (void (^)(PigeonUserDetails *_Nullable, FlutterError *_Nullable))completion; +- (void)updatePhoneNumberApp:(PigeonFirebaseApp *)app + input:(NSDictionary *)input + completion: + (void (^)(PigeonUserDetails *_Nullable, FlutterError *_Nullable))completion; +- (void)updateProfileApp:(PigeonFirebaseApp *)app + profile:(PigeonUserProfile *)profile + completion: + (void (^)(PigeonUserDetails *_Nullable, FlutterError *_Nullable))completion; +- (void)verifyBeforeUpdateEmailApp:(PigeonFirebaseApp *)app + newEmail:(NSString *)newEmail + actionCodeSettings:(nullable PigeonActionCodeSettings *)actionCodeSettings + completion:(void (^)(FlutterError *_Nullable))completion; +@end + +extern void FirebaseAuthUserHostApiSetup(id binaryMessenger, + NSObject *_Nullable api); + /// The codec used by MultiFactorUserHostApi. NSObject *MultiFactorUserHostApiGetCodec(void); @protocol MultiFactorUserHostApi -- (void)enrollPhoneAppName:(NSString *)appName - assertion:(PigeonPhoneMultiFactorAssertion *)assertion - displayName:(nullable NSString *)displayName - completion:(void (^)(FlutterError *_Nullable))completion; -- (void)getSessionAppName:(NSString *)appName - completion:(void (^)(PigeonMultiFactorSession *_Nullable, - FlutterError *_Nullable))completion; -- (void)unenrollAppName:(NSString *)appName - factorUid:(nullable NSString *)factorUid - completion:(void (^)(FlutterError *_Nullable))completion; -- (void)getEnrolledFactorsAppName:(NSString *)appName - completion:(void (^)(NSArray *_Nullable, - FlutterError *_Nullable))completion; +- (void)enrollPhoneApp:(PigeonFirebaseApp *)app + assertion:(PigeonPhoneMultiFactorAssertion *)assertion + displayName:(nullable NSString *)displayName + completion:(void (^)(FlutterError *_Nullable))completion; +- (void)getSessionApp:(PigeonFirebaseApp *)app + completion: + (void (^)(PigeonMultiFactorSession *_Nullable, FlutterError *_Nullable))completion; +- (void)unenrollApp:(PigeonFirebaseApp *)app + factorUid:(NSString *)factorUid + completion:(void (^)(FlutterError *_Nullable))completion; +- (void)getEnrolledFactorsApp:(PigeonFirebaseApp *)app + completion:(void (^)(NSArray *_Nullable, + FlutterError *_Nullable))completion; @end extern void MultiFactorUserHostApiSetup(id binaryMessenger, @@ -71,7 +440,7 @@ NSObject *MultiFactoResolverHostApiGetCodec(void); @protocol MultiFactoResolverHostApi - (void)resolveSignInResolverId:(NSString *)resolverId assertion:(PigeonPhoneMultiFactorAssertion *)assertion - completion:(void (^)(NSDictionary *_Nullable, + completion:(void (^)(PigeonUserCredential *_Nullable, FlutterError *_Nullable))completion; @end @@ -81,6 +450,7 @@ extern void MultiFactoResolverHostApiSetup(id binaryMess /// The codec used by GenerateInterfaces. NSObject *GenerateInterfacesGetCodec(void); +/// Only used to generate the object interface that are use outside of the Pigeon interface @protocol GenerateInterfaces - (void)generateInterfacesInfo:(PigeonMultiFactorInfo *)info error:(FlutterError *_Nullable *_Nonnull)error; diff --git a/packages/firebase_auth/firebase_auth/ios/Classes/messages.g.m b/packages/firebase_auth/firebase_auth/ios/Classes/messages.g.m index 1159e86ffa16..908d93b67a07 100644 --- a/packages/firebase_auth/firebase_auth/ios/Classes/messages.g.m +++ b/packages/firebase_auth/firebase_auth/ios/Classes/messages.g.m @@ -1,6 +1,7 @@ -// Autogenerated from Pigeon (v3.2.3), do not edit directly. +// Autogenerated from Pigeon (v9.2.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -#import "Public/messages.g.h" + +#import "messages.g.h" #if TARGET_OS_OSX #import #else @@ -11,23 +12,13 @@ #error File requires ARC to be enabled. #endif -static NSDictionary *wrapResult(id result, FlutterError *error) { - NSDictionary *errorDict = (NSDictionary *)[NSNull null]; +static NSArray *wrapResult(id result, FlutterError *error) { if (error) { - errorDict = @{ - @"code" : (error.code ?: [NSNull null]), - @"message" : (error.message ?: [NSNull null]), - @"details" : (error.details ?: [NSNull null]), - }; - } - return @{ - @"result" : (result ?: [NSNull null]), - @"error" : errorDict, - }; -} -static id GetNullableObject(NSDictionary *dict, id key) { - id result = dict[key]; - return (result == [NSNull null]) ? nil : result; + return @[ + error.code ?: [NSNull null], error.message ?: [NSNull null], error.details ?: [NSNull null] + ]; + } + return @[ result ?: [NSNull null] ]; } static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { id result = array[key]; @@ -35,19 +26,105 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { } @interface PigeonMultiFactorSession () -+ (PigeonMultiFactorSession *)fromMap:(NSDictionary *)dict; -+ (nullable PigeonMultiFactorSession *)nullableFromMap:(NSDictionary *)dict; -- (NSDictionary *)toMap; ++ (PigeonMultiFactorSession *)fromList:(NSArray *)list; ++ (nullable PigeonMultiFactorSession *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end + @interface PigeonPhoneMultiFactorAssertion () -+ (PigeonPhoneMultiFactorAssertion *)fromMap:(NSDictionary *)dict; -+ (nullable PigeonPhoneMultiFactorAssertion *)nullableFromMap:(NSDictionary *)dict; -- (NSDictionary *)toMap; ++ (PigeonPhoneMultiFactorAssertion *)fromList:(NSArray *)list; ++ (nullable PigeonPhoneMultiFactorAssertion *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end + @interface PigeonMultiFactorInfo () -+ (PigeonMultiFactorInfo *)fromMap:(NSDictionary *)dict; -+ (nullable PigeonMultiFactorInfo *)nullableFromMap:(NSDictionary *)dict; -- (NSDictionary *)toMap; ++ (PigeonMultiFactorInfo *)fromList:(NSArray *)list; ++ (nullable PigeonMultiFactorInfo *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonFirebaseApp () ++ (PigeonFirebaseApp *)fromList:(NSArray *)list; ++ (nullable PigeonFirebaseApp *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonActionCodeInfo () ++ (PigeonActionCodeInfo *)fromList:(NSArray *)list; ++ (nullable PigeonActionCodeInfo *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonActionCodeInfoData () ++ (PigeonActionCodeInfoData *)fromList:(NSArray *)list; ++ (nullable PigeonActionCodeInfoData *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonUserCredential () ++ (PigeonUserCredential *)fromList:(NSArray *)list; ++ (nullable PigeonUserCredential *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonAdditionalUserInfo () ++ (PigeonAdditionalUserInfo *)fromList:(NSArray *)list; ++ (nullable PigeonAdditionalUserInfo *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonAuthCredential () ++ (PigeonAuthCredential *)fromList:(NSArray *)list; ++ (nullable PigeonAuthCredential *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonUserInfo () ++ (PigeonUserInfo *)fromList:(NSArray *)list; ++ (nullable PigeonUserInfo *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonUserDetails () ++ (PigeonUserDetails *)fromList:(NSArray *)list; ++ (nullable PigeonUserDetails *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonActionCodeSettings () ++ (PigeonActionCodeSettings *)fromList:(NSArray *)list; ++ (nullable PigeonActionCodeSettings *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonFirebaseAuthSettings () ++ (PigeonFirebaseAuthSettings *)fromList:(NSArray *)list; ++ (nullable PigeonFirebaseAuthSettings *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonSignInProvider () ++ (PigeonSignInProvider *)fromList:(NSArray *)list; ++ (nullable PigeonSignInProvider *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonVerifyPhoneNumberRequest () ++ (PigeonVerifyPhoneNumberRequest *)fromList:(NSArray *)list; ++ (nullable PigeonVerifyPhoneNumberRequest *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonIdTokenResult () ++ (PigeonIdTokenResult *)fromList:(NSArray *)list; ++ (nullable PigeonIdTokenResult *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonUserProfile () ++ (PigeonUserProfile *)fromList:(NSArray *)list; ++ (nullable PigeonUserProfile *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end @implementation PigeonMultiFactorSession @@ -56,102 +133,1750 @@ + (instancetype)makeWithId:(NSString *)id { pigeonResult.id = id; return pigeonResult; } -+ (PigeonMultiFactorSession *)fromMap:(NSDictionary *)dict { ++ (PigeonMultiFactorSession *)fromList:(NSArray *)list { PigeonMultiFactorSession *pigeonResult = [[PigeonMultiFactorSession alloc] init]; - pigeonResult.id = GetNullableObject(dict, @"id"); + pigeonResult.id = GetNullableObjectAtIndex(list, 0); NSAssert(pigeonResult.id != nil, @""); return pigeonResult; } -+ (nullable PigeonMultiFactorSession *)nullableFromMap:(NSDictionary *)dict { - return (dict) ? [PigeonMultiFactorSession fromMap:dict] : nil; ++ (nullable PigeonMultiFactorSession *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonMultiFactorSession fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.id ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonPhoneMultiFactorAssertion ++ (instancetype)makeWithVerificationId:(NSString *)verificationId + verificationCode:(NSString *)verificationCode { + PigeonPhoneMultiFactorAssertion *pigeonResult = [[PigeonPhoneMultiFactorAssertion alloc] init]; + pigeonResult.verificationId = verificationId; + pigeonResult.verificationCode = verificationCode; + return pigeonResult; +} ++ (PigeonPhoneMultiFactorAssertion *)fromList:(NSArray *)list { + PigeonPhoneMultiFactorAssertion *pigeonResult = [[PigeonPhoneMultiFactorAssertion alloc] init]; + pigeonResult.verificationId = GetNullableObjectAtIndex(list, 0); + NSAssert(pigeonResult.verificationId != nil, @""); + pigeonResult.verificationCode = GetNullableObjectAtIndex(list, 1); + NSAssert(pigeonResult.verificationCode != nil, @""); + return pigeonResult; +} ++ (nullable PigeonPhoneMultiFactorAssertion *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonPhoneMultiFactorAssertion fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.verificationId ?: [NSNull null]), + (self.verificationCode ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonMultiFactorInfo ++ (instancetype)makeWithDisplayName:(nullable NSString *)displayName + enrollmentTimestamp:(NSNumber *)enrollmentTimestamp + factorId:(nullable NSString *)factorId + uid:(NSString *)uid + phoneNumber:(nullable NSString *)phoneNumber { + PigeonMultiFactorInfo *pigeonResult = [[PigeonMultiFactorInfo alloc] init]; + pigeonResult.displayName = displayName; + pigeonResult.enrollmentTimestamp = enrollmentTimestamp; + pigeonResult.factorId = factorId; + pigeonResult.uid = uid; + pigeonResult.phoneNumber = phoneNumber; + return pigeonResult; +} ++ (PigeonMultiFactorInfo *)fromList:(NSArray *)list { + PigeonMultiFactorInfo *pigeonResult = [[PigeonMultiFactorInfo alloc] init]; + pigeonResult.displayName = GetNullableObjectAtIndex(list, 0); + pigeonResult.enrollmentTimestamp = GetNullableObjectAtIndex(list, 1); + NSAssert(pigeonResult.enrollmentTimestamp != nil, @""); + pigeonResult.factorId = GetNullableObjectAtIndex(list, 2); + pigeonResult.uid = GetNullableObjectAtIndex(list, 3); + NSAssert(pigeonResult.uid != nil, @""); + pigeonResult.phoneNumber = GetNullableObjectAtIndex(list, 4); + return pigeonResult; +} ++ (nullable PigeonMultiFactorInfo *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonMultiFactorInfo fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.displayName ?: [NSNull null]), + (self.enrollmentTimestamp ?: [NSNull null]), + (self.factorId ?: [NSNull null]), + (self.uid ?: [NSNull null]), + (self.phoneNumber ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonFirebaseApp ++ (instancetype)makeWithAppName:(NSString *)appName tenantId:(nullable NSString *)tenantId { + PigeonFirebaseApp *pigeonResult = [[PigeonFirebaseApp alloc] init]; + pigeonResult.appName = appName; + pigeonResult.tenantId = tenantId; + return pigeonResult; +} ++ (PigeonFirebaseApp *)fromList:(NSArray *)list { + PigeonFirebaseApp *pigeonResult = [[PigeonFirebaseApp alloc] init]; + pigeonResult.appName = GetNullableObjectAtIndex(list, 0); + NSAssert(pigeonResult.appName != nil, @""); + pigeonResult.tenantId = GetNullableObjectAtIndex(list, 1); + return pigeonResult; +} ++ (nullable PigeonFirebaseApp *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonFirebaseApp fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.appName ?: [NSNull null]), + (self.tenantId ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonActionCodeInfo ++ (instancetype)makeWithOperation:(ActionCodeInfoOperation)operation + data:(PigeonActionCodeInfoData *)data { + PigeonActionCodeInfo *pigeonResult = [[PigeonActionCodeInfo alloc] init]; + pigeonResult.operation = operation; + pigeonResult.data = data; + return pigeonResult; +} ++ (PigeonActionCodeInfo *)fromList:(NSArray *)list { + PigeonActionCodeInfo *pigeonResult = [[PigeonActionCodeInfo alloc] init]; + pigeonResult.operation = [GetNullableObjectAtIndex(list, 0) integerValue]; + pigeonResult.data = + [PigeonActionCodeInfoData nullableFromList:(GetNullableObjectAtIndex(list, 1))]; + NSAssert(pigeonResult.data != nil, @""); + return pigeonResult; +} ++ (nullable PigeonActionCodeInfo *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonActionCodeInfo fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + @(self.operation), + (self.data ? [self.data toList] : [NSNull null]), + ]; +} +@end + +@implementation PigeonActionCodeInfoData ++ (instancetype)makeWithEmail:(nullable NSString *)email + previousEmail:(nullable NSString *)previousEmail { + PigeonActionCodeInfoData *pigeonResult = [[PigeonActionCodeInfoData alloc] init]; + pigeonResult.email = email; + pigeonResult.previousEmail = previousEmail; + return pigeonResult; +} ++ (PigeonActionCodeInfoData *)fromList:(NSArray *)list { + PigeonActionCodeInfoData *pigeonResult = [[PigeonActionCodeInfoData alloc] init]; + pigeonResult.email = GetNullableObjectAtIndex(list, 0); + pigeonResult.previousEmail = GetNullableObjectAtIndex(list, 1); + return pigeonResult; +} ++ (nullable PigeonActionCodeInfoData *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonActionCodeInfoData fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.email ?: [NSNull null]), + (self.previousEmail ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonUserCredential ++ (instancetype)makeWithUser:(nullable PigeonUserDetails *)user + additionalUserInfo:(nullable PigeonAdditionalUserInfo *)additionalUserInfo + credential:(nullable PigeonAuthCredential *)credential { + PigeonUserCredential *pigeonResult = [[PigeonUserCredential alloc] init]; + pigeonResult.user = user; + pigeonResult.additionalUserInfo = additionalUserInfo; + pigeonResult.credential = credential; + return pigeonResult; +} ++ (PigeonUserCredential *)fromList:(NSArray *)list { + PigeonUserCredential *pigeonResult = [[PigeonUserCredential alloc] init]; + pigeonResult.user = [PigeonUserDetails nullableFromList:(GetNullableObjectAtIndex(list, 0))]; + pigeonResult.additionalUserInfo = + [PigeonAdditionalUserInfo nullableFromList:(GetNullableObjectAtIndex(list, 1))]; + pigeonResult.credential = + [PigeonAuthCredential nullableFromList:(GetNullableObjectAtIndex(list, 2))]; + return pigeonResult; +} ++ (nullable PigeonUserCredential *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonUserCredential fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.user ? [self.user toList] : [NSNull null]), + (self.additionalUserInfo ? [self.additionalUserInfo toList] : [NSNull null]), + (self.credential ? [self.credential toList] : [NSNull null]), + ]; +} +@end + +@implementation PigeonAdditionalUserInfo ++ (instancetype)makeWithIsNewUser:(NSNumber *)isNewUser + providerId:(nullable NSString *)providerId + username:(nullable NSString *)username + profile:(nullable NSDictionary *)profile { + PigeonAdditionalUserInfo *pigeonResult = [[PigeonAdditionalUserInfo alloc] init]; + pigeonResult.isNewUser = isNewUser; + pigeonResult.providerId = providerId; + pigeonResult.username = username; + pigeonResult.profile = profile; + return pigeonResult; +} ++ (PigeonAdditionalUserInfo *)fromList:(NSArray *)list { + PigeonAdditionalUserInfo *pigeonResult = [[PigeonAdditionalUserInfo alloc] init]; + pigeonResult.isNewUser = GetNullableObjectAtIndex(list, 0); + NSAssert(pigeonResult.isNewUser != nil, @""); + pigeonResult.providerId = GetNullableObjectAtIndex(list, 1); + pigeonResult.username = GetNullableObjectAtIndex(list, 2); + pigeonResult.profile = GetNullableObjectAtIndex(list, 3); + return pigeonResult; +} ++ (nullable PigeonAdditionalUserInfo *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonAdditionalUserInfo fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.isNewUser ?: [NSNull null]), + (self.providerId ?: [NSNull null]), + (self.username ?: [NSNull null]), + (self.profile ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonAuthCredential ++ (instancetype)makeWithProviderId:(NSString *)providerId + signInMethod:(NSString *)signInMethod + nativeId:(NSNumber *)nativeId + accessToken:(nullable NSString *)accessToken { + PigeonAuthCredential *pigeonResult = [[PigeonAuthCredential alloc] init]; + pigeonResult.providerId = providerId; + pigeonResult.signInMethod = signInMethod; + pigeonResult.nativeId = nativeId; + pigeonResult.accessToken = accessToken; + return pigeonResult; +} ++ (PigeonAuthCredential *)fromList:(NSArray *)list { + PigeonAuthCredential *pigeonResult = [[PigeonAuthCredential alloc] init]; + pigeonResult.providerId = GetNullableObjectAtIndex(list, 0); + NSAssert(pigeonResult.providerId != nil, @""); + pigeonResult.signInMethod = GetNullableObjectAtIndex(list, 1); + NSAssert(pigeonResult.signInMethod != nil, @""); + pigeonResult.nativeId = GetNullableObjectAtIndex(list, 2); + NSAssert(pigeonResult.nativeId != nil, @""); + pigeonResult.accessToken = GetNullableObjectAtIndex(list, 3); + return pigeonResult; +} ++ (nullable PigeonAuthCredential *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonAuthCredential fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.providerId ?: [NSNull null]), + (self.signInMethod ?: [NSNull null]), + (self.nativeId ?: [NSNull null]), + (self.accessToken ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonUserInfo ++ (instancetype)makeWithUid:(NSString *)uid + email:(nullable NSString *)email + displayName:(nullable NSString *)displayName + photoUrl:(nullable NSString *)photoUrl + phoneNumber:(nullable NSString *)phoneNumber + isAnonymous:(NSNumber *)isAnonymous + isEmailVerified:(NSNumber *)isEmailVerified + providerId:(nullable NSString *)providerId + tenantId:(nullable NSString *)tenantId + refreshToken:(nullable NSString *)refreshToken + creationTimestamp:(nullable NSNumber *)creationTimestamp + lastSignInTimestamp:(nullable NSNumber *)lastSignInTimestamp { + PigeonUserInfo *pigeonResult = [[PigeonUserInfo alloc] init]; + pigeonResult.uid = uid; + pigeonResult.email = email; + pigeonResult.displayName = displayName; + pigeonResult.photoUrl = photoUrl; + pigeonResult.phoneNumber = phoneNumber; + pigeonResult.isAnonymous = isAnonymous; + pigeonResult.isEmailVerified = isEmailVerified; + pigeonResult.providerId = providerId; + pigeonResult.tenantId = tenantId; + pigeonResult.refreshToken = refreshToken; + pigeonResult.creationTimestamp = creationTimestamp; + pigeonResult.lastSignInTimestamp = lastSignInTimestamp; + return pigeonResult; +} ++ (PigeonUserInfo *)fromList:(NSArray *)list { + PigeonUserInfo *pigeonResult = [[PigeonUserInfo alloc] init]; + pigeonResult.uid = GetNullableObjectAtIndex(list, 0); + NSAssert(pigeonResult.uid != nil, @""); + pigeonResult.email = GetNullableObjectAtIndex(list, 1); + pigeonResult.displayName = GetNullableObjectAtIndex(list, 2); + pigeonResult.photoUrl = GetNullableObjectAtIndex(list, 3); + pigeonResult.phoneNumber = GetNullableObjectAtIndex(list, 4); + pigeonResult.isAnonymous = GetNullableObjectAtIndex(list, 5); + NSAssert(pigeonResult.isAnonymous != nil, @""); + pigeonResult.isEmailVerified = GetNullableObjectAtIndex(list, 6); + NSAssert(pigeonResult.isEmailVerified != nil, @""); + pigeonResult.providerId = GetNullableObjectAtIndex(list, 7); + pigeonResult.tenantId = GetNullableObjectAtIndex(list, 8); + pigeonResult.refreshToken = GetNullableObjectAtIndex(list, 9); + pigeonResult.creationTimestamp = GetNullableObjectAtIndex(list, 10); + pigeonResult.lastSignInTimestamp = GetNullableObjectAtIndex(list, 11); + return pigeonResult; +} ++ (nullable PigeonUserInfo *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonUserInfo fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.uid ?: [NSNull null]), + (self.email ?: [NSNull null]), + (self.displayName ?: [NSNull null]), + (self.photoUrl ?: [NSNull null]), + (self.phoneNumber ?: [NSNull null]), + (self.isAnonymous ?: [NSNull null]), + (self.isEmailVerified ?: [NSNull null]), + (self.providerId ?: [NSNull null]), + (self.tenantId ?: [NSNull null]), + (self.refreshToken ?: [NSNull null]), + (self.creationTimestamp ?: [NSNull null]), + (self.lastSignInTimestamp ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonUserDetails ++ (instancetype)makeWithUserInfo:(PigeonUserInfo *)userInfo + providerData:(NSArray *> *)providerData { + PigeonUserDetails *pigeonResult = [[PigeonUserDetails alloc] init]; + pigeonResult.userInfo = userInfo; + pigeonResult.providerData = providerData; + return pigeonResult; +} ++ (PigeonUserDetails *)fromList:(NSArray *)list { + PigeonUserDetails *pigeonResult = [[PigeonUserDetails alloc] init]; + pigeonResult.userInfo = [PigeonUserInfo nullableFromList:(GetNullableObjectAtIndex(list, 0))]; + NSAssert(pigeonResult.userInfo != nil, @""); + pigeonResult.providerData = GetNullableObjectAtIndex(list, 1); + NSAssert(pigeonResult.providerData != nil, @""); + return pigeonResult; +} ++ (nullable PigeonUserDetails *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonUserDetails fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.userInfo ? [self.userInfo toList] : [NSNull null]), + (self.providerData ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonActionCodeSettings ++ (instancetype)makeWithUrl:(NSString *)url + dynamicLinkDomain:(nullable NSString *)dynamicLinkDomain + handleCodeInApp:(NSNumber *)handleCodeInApp + iOSBundleId:(nullable NSString *)iOSBundleId + androidPackageName:(nullable NSString *)androidPackageName + androidInstallApp:(NSNumber *)androidInstallApp + androidMinimumVersion:(nullable NSString *)androidMinimumVersion { + PigeonActionCodeSettings *pigeonResult = [[PigeonActionCodeSettings alloc] init]; + pigeonResult.url = url; + pigeonResult.dynamicLinkDomain = dynamicLinkDomain; + pigeonResult.handleCodeInApp = handleCodeInApp; + pigeonResult.iOSBundleId = iOSBundleId; + pigeonResult.androidPackageName = androidPackageName; + pigeonResult.androidInstallApp = androidInstallApp; + pigeonResult.androidMinimumVersion = androidMinimumVersion; + return pigeonResult; +} ++ (PigeonActionCodeSettings *)fromList:(NSArray *)list { + PigeonActionCodeSettings *pigeonResult = [[PigeonActionCodeSettings alloc] init]; + pigeonResult.url = GetNullableObjectAtIndex(list, 0); + NSAssert(pigeonResult.url != nil, @""); + pigeonResult.dynamicLinkDomain = GetNullableObjectAtIndex(list, 1); + pigeonResult.handleCodeInApp = GetNullableObjectAtIndex(list, 2); + NSAssert(pigeonResult.handleCodeInApp != nil, @""); + pigeonResult.iOSBundleId = GetNullableObjectAtIndex(list, 3); + pigeonResult.androidPackageName = GetNullableObjectAtIndex(list, 4); + pigeonResult.androidInstallApp = GetNullableObjectAtIndex(list, 5); + NSAssert(pigeonResult.androidInstallApp != nil, @""); + pigeonResult.androidMinimumVersion = GetNullableObjectAtIndex(list, 6); + return pigeonResult; +} ++ (nullable PigeonActionCodeSettings *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonActionCodeSettings fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.url ?: [NSNull null]), + (self.dynamicLinkDomain ?: [NSNull null]), + (self.handleCodeInApp ?: [NSNull null]), + (self.iOSBundleId ?: [NSNull null]), + (self.androidPackageName ?: [NSNull null]), + (self.androidInstallApp ?: [NSNull null]), + (self.androidMinimumVersion ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonFirebaseAuthSettings ++ (instancetype)makeWithAppVerificationDisabledForTesting: + (NSNumber *)appVerificationDisabledForTesting + userAccessGroup:(nullable NSString *)userAccessGroup + phoneNumber:(nullable NSString *)phoneNumber + smsCode:(nullable NSString *)smsCode + forceRecaptchaFlow:(nullable NSNumber *)forceRecaptchaFlow { + PigeonFirebaseAuthSettings *pigeonResult = [[PigeonFirebaseAuthSettings alloc] init]; + pigeonResult.appVerificationDisabledForTesting = appVerificationDisabledForTesting; + pigeonResult.userAccessGroup = userAccessGroup; + pigeonResult.phoneNumber = phoneNumber; + pigeonResult.smsCode = smsCode; + pigeonResult.forceRecaptchaFlow = forceRecaptchaFlow; + return pigeonResult; +} ++ (PigeonFirebaseAuthSettings *)fromList:(NSArray *)list { + PigeonFirebaseAuthSettings *pigeonResult = [[PigeonFirebaseAuthSettings alloc] init]; + pigeonResult.appVerificationDisabledForTesting = GetNullableObjectAtIndex(list, 0); + NSAssert(pigeonResult.appVerificationDisabledForTesting != nil, @""); + pigeonResult.userAccessGroup = GetNullableObjectAtIndex(list, 1); + pigeonResult.phoneNumber = GetNullableObjectAtIndex(list, 2); + pigeonResult.smsCode = GetNullableObjectAtIndex(list, 3); + pigeonResult.forceRecaptchaFlow = GetNullableObjectAtIndex(list, 4); + return pigeonResult; +} ++ (nullable PigeonFirebaseAuthSettings *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonFirebaseAuthSettings fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.appVerificationDisabledForTesting ?: [NSNull null]), + (self.userAccessGroup ?: [NSNull null]), + (self.phoneNumber ?: [NSNull null]), + (self.smsCode ?: [NSNull null]), + (self.forceRecaptchaFlow ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonSignInProvider ++ (instancetype)makeWithProviderId:(NSString *)providerId + scopes:(nullable NSArray *)scopes + customParameters: + (nullable NSDictionary *)customParameters { + PigeonSignInProvider *pigeonResult = [[PigeonSignInProvider alloc] init]; + pigeonResult.providerId = providerId; + pigeonResult.scopes = scopes; + pigeonResult.customParameters = customParameters; + return pigeonResult; +} ++ (PigeonSignInProvider *)fromList:(NSArray *)list { + PigeonSignInProvider *pigeonResult = [[PigeonSignInProvider alloc] init]; + pigeonResult.providerId = GetNullableObjectAtIndex(list, 0); + NSAssert(pigeonResult.providerId != nil, @""); + pigeonResult.scopes = GetNullableObjectAtIndex(list, 1); + pigeonResult.customParameters = GetNullableObjectAtIndex(list, 2); + return pigeonResult; +} ++ (nullable PigeonSignInProvider *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonSignInProvider fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.providerId ?: [NSNull null]), + (self.scopes ?: [NSNull null]), + (self.customParameters ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonVerifyPhoneNumberRequest ++ (instancetype)makeWithPhoneNumber:(nullable NSString *)phoneNumber + timeout:(NSNumber *)timeout + forceResendingToken:(nullable NSNumber *)forceResendingToken + autoRetrievedSmsCodeForTesting:(nullable NSString *)autoRetrievedSmsCodeForTesting + multiFactorInfoId:(nullable NSString *)multiFactorInfoId + multiFactorSessionId:(nullable NSString *)multiFactorSessionId { + PigeonVerifyPhoneNumberRequest *pigeonResult = [[PigeonVerifyPhoneNumberRequest alloc] init]; + pigeonResult.phoneNumber = phoneNumber; + pigeonResult.timeout = timeout; + pigeonResult.forceResendingToken = forceResendingToken; + pigeonResult.autoRetrievedSmsCodeForTesting = autoRetrievedSmsCodeForTesting; + pigeonResult.multiFactorInfoId = multiFactorInfoId; + pigeonResult.multiFactorSessionId = multiFactorSessionId; + return pigeonResult; +} ++ (PigeonVerifyPhoneNumberRequest *)fromList:(NSArray *)list { + PigeonVerifyPhoneNumberRequest *pigeonResult = [[PigeonVerifyPhoneNumberRequest alloc] init]; + pigeonResult.phoneNumber = GetNullableObjectAtIndex(list, 0); + pigeonResult.timeout = GetNullableObjectAtIndex(list, 1); + NSAssert(pigeonResult.timeout != nil, @""); + pigeonResult.forceResendingToken = GetNullableObjectAtIndex(list, 2); + pigeonResult.autoRetrievedSmsCodeForTesting = GetNullableObjectAtIndex(list, 3); + pigeonResult.multiFactorInfoId = GetNullableObjectAtIndex(list, 4); + pigeonResult.multiFactorSessionId = GetNullableObjectAtIndex(list, 5); + return pigeonResult; +} ++ (nullable PigeonVerifyPhoneNumberRequest *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonVerifyPhoneNumberRequest fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.phoneNumber ?: [NSNull null]), + (self.timeout ?: [NSNull null]), + (self.forceResendingToken ?: [NSNull null]), + (self.autoRetrievedSmsCodeForTesting ?: [NSNull null]), + (self.multiFactorInfoId ?: [NSNull null]), + (self.multiFactorSessionId ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonIdTokenResult ++ (instancetype)makeWithToken:(nullable NSString *)token + expirationTimestamp:(nullable NSNumber *)expirationTimestamp + authTimestamp:(nullable NSNumber *)authTimestamp + issuedAtTimestamp:(nullable NSNumber *)issuedAtTimestamp + signInProvider:(nullable NSString *)signInProvider + claims:(nullable NSDictionary *)claims + signInSecondFactor:(nullable NSString *)signInSecondFactor { + PigeonIdTokenResult *pigeonResult = [[PigeonIdTokenResult alloc] init]; + pigeonResult.token = token; + pigeonResult.expirationTimestamp = expirationTimestamp; + pigeonResult.authTimestamp = authTimestamp; + pigeonResult.issuedAtTimestamp = issuedAtTimestamp; + pigeonResult.signInProvider = signInProvider; + pigeonResult.claims = claims; + pigeonResult.signInSecondFactor = signInSecondFactor; + return pigeonResult; +} ++ (PigeonIdTokenResult *)fromList:(NSArray *)list { + PigeonIdTokenResult *pigeonResult = [[PigeonIdTokenResult alloc] init]; + pigeonResult.token = GetNullableObjectAtIndex(list, 0); + pigeonResult.expirationTimestamp = GetNullableObjectAtIndex(list, 1); + pigeonResult.authTimestamp = GetNullableObjectAtIndex(list, 2); + pigeonResult.issuedAtTimestamp = GetNullableObjectAtIndex(list, 3); + pigeonResult.signInProvider = GetNullableObjectAtIndex(list, 4); + pigeonResult.claims = GetNullableObjectAtIndex(list, 5); + pigeonResult.signInSecondFactor = GetNullableObjectAtIndex(list, 6); + return pigeonResult; +} ++ (nullable PigeonIdTokenResult *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonIdTokenResult fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.token ?: [NSNull null]), + (self.expirationTimestamp ?: [NSNull null]), + (self.authTimestamp ?: [NSNull null]), + (self.issuedAtTimestamp ?: [NSNull null]), + (self.signInProvider ?: [NSNull null]), + (self.claims ?: [NSNull null]), + (self.signInSecondFactor ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonUserProfile ++ (instancetype)makeWithDisplayName:(nullable NSString *)displayName + photoUrl:(nullable NSString *)photoUrl + displayNameChanged:(NSNumber *)displayNameChanged + photoUrlChanged:(NSNumber *)photoUrlChanged { + PigeonUserProfile *pigeonResult = [[PigeonUserProfile alloc] init]; + pigeonResult.displayName = displayName; + pigeonResult.photoUrl = photoUrl; + pigeonResult.displayNameChanged = displayNameChanged; + pigeonResult.photoUrlChanged = photoUrlChanged; + return pigeonResult; +} ++ (PigeonUserProfile *)fromList:(NSArray *)list { + PigeonUserProfile *pigeonResult = [[PigeonUserProfile alloc] init]; + pigeonResult.displayName = GetNullableObjectAtIndex(list, 0); + pigeonResult.photoUrl = GetNullableObjectAtIndex(list, 1); + pigeonResult.displayNameChanged = GetNullableObjectAtIndex(list, 2); + NSAssert(pigeonResult.displayNameChanged != nil, @""); + pigeonResult.photoUrlChanged = GetNullableObjectAtIndex(list, 3); + NSAssert(pigeonResult.photoUrlChanged != nil, @""); + return pigeonResult; +} ++ (nullable PigeonUserProfile *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonUserProfile fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.displayName ?: [NSNull null]), + (self.photoUrl ?: [NSNull null]), + (self.displayNameChanged ?: [NSNull null]), + (self.photoUrlChanged ?: [NSNull null]), + ]; +} +@end + +@interface FirebaseAuthHostApiCodecReader : FlutterStandardReader +@end +@implementation FirebaseAuthHostApiCodecReader +- (nullable id)readValueOfType:(UInt8)type { + switch (type) { + case 128: + return [PigeonActionCodeInfo fromList:[self readValue]]; + case 129: + return [PigeonActionCodeInfoData fromList:[self readValue]]; + case 130: + return [PigeonActionCodeSettings fromList:[self readValue]]; + case 131: + return [PigeonAdditionalUserInfo fromList:[self readValue]]; + case 132: + return [PigeonAuthCredential fromList:[self readValue]]; + case 133: + return [PigeonFirebaseApp fromList:[self readValue]]; + case 134: + return [PigeonFirebaseAuthSettings fromList:[self readValue]]; + case 135: + return [PigeonIdTokenResult fromList:[self readValue]]; + case 136: + return [PigeonMultiFactorInfo fromList:[self readValue]]; + case 137: + return [PigeonMultiFactorSession fromList:[self readValue]]; + case 138: + return [PigeonPhoneMultiFactorAssertion fromList:[self readValue]]; + case 139: + return [PigeonSignInProvider fromList:[self readValue]]; + case 140: + return [PigeonUserCredential fromList:[self readValue]]; + case 141: + return [PigeonUserDetails fromList:[self readValue]]; + case 142: + return [PigeonUserInfo fromList:[self readValue]]; + case 143: + return [PigeonUserProfile fromList:[self readValue]]; + case 144: + return [PigeonVerifyPhoneNumberRequest fromList:[self readValue]]; + default: + return [super readValueOfType:type]; + } +} +@end + +@interface FirebaseAuthHostApiCodecWriter : FlutterStandardWriter +@end +@implementation FirebaseAuthHostApiCodecWriter +- (void)writeValue:(id)value { + if ([value isKindOfClass:[PigeonActionCodeInfo class]]) { + [self writeByte:128]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonActionCodeInfoData class]]) { + [self writeByte:129]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonActionCodeSettings class]]) { + [self writeByte:130]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonAdditionalUserInfo class]]) { + [self writeByte:131]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonAuthCredential class]]) { + [self writeByte:132]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonFirebaseApp class]]) { + [self writeByte:133]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonFirebaseAuthSettings class]]) { + [self writeByte:134]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonIdTokenResult class]]) { + [self writeByte:135]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonMultiFactorInfo class]]) { + [self writeByte:136]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonMultiFactorSession class]]) { + [self writeByte:137]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonPhoneMultiFactorAssertion class]]) { + [self writeByte:138]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonSignInProvider class]]) { + [self writeByte:139]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonUserCredential class]]) { + [self writeByte:140]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonUserDetails class]]) { + [self writeByte:141]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonUserInfo class]]) { + [self writeByte:142]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonUserProfile class]]) { + [self writeByte:143]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonVerifyPhoneNumberRequest class]]) { + [self writeByte:144]; + [self writeValue:[value toList]]; + } else { + [super writeValue:value]; + } +} +@end + +@interface FirebaseAuthHostApiCodecReaderWriter : FlutterStandardReaderWriter +@end +@implementation FirebaseAuthHostApiCodecReaderWriter +- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data { + return [[FirebaseAuthHostApiCodecWriter alloc] initWithData:data]; +} +- (FlutterStandardReader *)readerWithData:(NSData *)data { + return [[FirebaseAuthHostApiCodecReader alloc] initWithData:data]; +} +@end + +NSObject *FirebaseAuthHostApiGetCodec(void) { + static FlutterStandardMessageCodec *sSharedObject = nil; + static dispatch_once_t sPred = 0; + dispatch_once(&sPred, ^{ + FirebaseAuthHostApiCodecReaderWriter *readerWriter = + [[FirebaseAuthHostApiCodecReaderWriter alloc] init]; + sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; + }); + return sSharedObject; +} + +void FirebaseAuthHostApiSetup(id binaryMessenger, + NSObject *api) { + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.registerIdTokenListener" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(registerIdTokenListenerApp:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(registerIdTokenListenerApp:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + [api registerIdTokenListenerApp:arg_app + completion:^(NSString *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.registerAuthStateListener" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(registerAuthStateListenerApp:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(registerAuthStateListenerApp:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + [api registerAuthStateListenerApp:arg_app + completion:^(NSString *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.useEmulator" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(useEmulatorApp:host:port:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(useEmulatorApp:host:port:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_host = GetNullableObjectAtIndex(args, 1); + NSNumber *arg_port = GetNullableObjectAtIndex(args, 2); + [api useEmulatorApp:arg_app + host:arg_host + port:arg_port + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.applyActionCode" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(applyActionCodeApp:code:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(applyActionCodeApp:code:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_code = GetNullableObjectAtIndex(args, 1); + [api applyActionCodeApp:arg_app + code:arg_code + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.checkActionCode" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(checkActionCodeApp:code:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(checkActionCodeApp:code:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_code = GetNullableObjectAtIndex(args, 1); + [api checkActionCodeApp:arg_app + code:arg_code + completion:^(PigeonActionCodeInfo *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.confirmPasswordReset" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(confirmPasswordResetApp: + code:newPassword:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(confirmPasswordResetApp:code:newPassword:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_code = GetNullableObjectAtIndex(args, 1); + NSString *arg_newPassword = GetNullableObjectAtIndex(args, 2); + [api confirmPasswordResetApp:arg_app + code:arg_code + newPassword:arg_newPassword + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.createUserWithEmailAndPassword" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector + (createUserWithEmailAndPasswordApp:email:password:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(createUserWithEmailAndPasswordApp:email:password:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_email = GetNullableObjectAtIndex(args, 1); + NSString *arg_password = GetNullableObjectAtIndex(args, 2); + [api createUserWithEmailAndPasswordApp:arg_app + email:arg_email + password:arg_password + completion:^(PigeonUserCredential *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.signInAnonymously" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(signInAnonymouslyApp:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(signInAnonymouslyApp:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + [api signInAnonymouslyApp:arg_app + completion:^(PigeonUserCredential *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.signInWithCredential" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(signInWithCredentialApp:input:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(signInWithCredentialApp:input:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSDictionary *arg_input = GetNullableObjectAtIndex(args, 1); + [api signInWithCredentialApp:arg_app + input:arg_input + completion:^(PigeonUserCredential *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.signInWithCustomToken" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(signInWithCustomTokenApp:token:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(signInWithCustomTokenApp:token:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_token = GetNullableObjectAtIndex(args, 1); + [api signInWithCustomTokenApp:arg_app + token:arg_token + completion:^(PigeonUserCredential *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailAndPassword" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector + (signInWithEmailAndPasswordApp:email:password:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(signInWithEmailAndPasswordApp:email:password:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_email = GetNullableObjectAtIndex(args, 1); + NSString *arg_password = GetNullableObjectAtIndex(args, 2); + [api signInWithEmailAndPasswordApp:arg_app + email:arg_email + password:arg_password + completion:^(PigeonUserCredential *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailLink" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(signInWithEmailLinkApp: + email:emailLink:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(signInWithEmailLinkApp:email:emailLink:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_email = GetNullableObjectAtIndex(args, 1); + NSString *arg_emailLink = GetNullableObjectAtIndex(args, 2); + [api signInWithEmailLinkApp:arg_app + email:arg_email + emailLink:arg_emailLink + completion:^(PigeonUserCredential *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.signInWithProvider" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(signInWithProviderApp: + signInProvider:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(signInWithProviderApp:signInProvider:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + PigeonSignInProvider *arg_signInProvider = GetNullableObjectAtIndex(args, 1); + [api signInWithProviderApp:arg_app + signInProvider:arg_signInProvider + completion:^(PigeonUserCredential *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.signOut" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert( + [api respondsToSelector:@selector(signOutApp:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to @selector(signOutApp:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + [api signOutApp:arg_app + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.fetchSignInMethodsForEmail" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(fetchSignInMethodsForEmailApp:email:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(fetchSignInMethodsForEmailApp:email:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_email = GetNullableObjectAtIndex(args, 1); + [api fetchSignInMethodsForEmailApp:arg_app + email:arg_email + completion:^(NSArray *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.sendPasswordResetEmail" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector + (sendPasswordResetEmailApp:email:actionCodeSettings:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(sendPasswordResetEmailApp:email:actionCodeSettings:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_email = GetNullableObjectAtIndex(args, 1); + PigeonActionCodeSettings *arg_actionCodeSettings = GetNullableObjectAtIndex(args, 2); + [api sendPasswordResetEmailApp:arg_app + email:arg_email + actionCodeSettings:arg_actionCodeSettings + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.sendSignInLinkToEmail" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector + (sendSignInLinkToEmailApp:email:actionCodeSettings:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(sendSignInLinkToEmailApp:email:actionCodeSettings:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_email = GetNullableObjectAtIndex(args, 1); + PigeonActionCodeSettings *arg_actionCodeSettings = GetNullableObjectAtIndex(args, 2); + [api sendSignInLinkToEmailApp:arg_app + email:arg_email + actionCodeSettings:arg_actionCodeSettings + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.setLanguageCode" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(setLanguageCodeApp:languageCode:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(setLanguageCodeApp:languageCode:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_languageCode = GetNullableObjectAtIndex(args, 1); + [api setLanguageCodeApp:arg_app + languageCode:arg_languageCode + completion:^(NSString *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.setSettings" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(setSettingsApp:settings:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(setSettingsApp:settings:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + PigeonFirebaseAuthSettings *arg_settings = GetNullableObjectAtIndex(args, 1); + [api setSettingsApp:arg_app + settings:arg_settings + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.verifyPasswordResetCode" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(verifyPasswordResetCodeApp:code:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(verifyPasswordResetCodeApp:code:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_code = GetNullableObjectAtIndex(args, 1); + [api verifyPasswordResetCodeApp:arg_app + code:arg_code + completion:^(NSString *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthHostApi.verifyPhoneNumber" + binaryMessenger:binaryMessenger + codec:FirebaseAuthHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(verifyPhoneNumberApp:request:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(verifyPhoneNumberApp:request:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + PigeonVerifyPhoneNumberRequest *arg_request = GetNullableObjectAtIndex(args, 1); + [api verifyPhoneNumberApp:arg_app + request:arg_request + completion:^(NSString *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } } -- (NSDictionary *)toMap { - return @{ - @"id" : (self.id ?: [NSNull null]), - }; +@interface FirebaseAuthUserHostApiCodecReader : FlutterStandardReader +@end +@implementation FirebaseAuthUserHostApiCodecReader +- (nullable id)readValueOfType:(UInt8)type { + switch (type) { + case 128: + return [PigeonActionCodeInfo fromList:[self readValue]]; + case 129: + return [PigeonActionCodeInfoData fromList:[self readValue]]; + case 130: + return [PigeonActionCodeSettings fromList:[self readValue]]; + case 131: + return [PigeonAdditionalUserInfo fromList:[self readValue]]; + case 132: + return [PigeonAuthCredential fromList:[self readValue]]; + case 133: + return [PigeonFirebaseApp fromList:[self readValue]]; + case 134: + return [PigeonFirebaseAuthSettings fromList:[self readValue]]; + case 135: + return [PigeonIdTokenResult fromList:[self readValue]]; + case 136: + return [PigeonMultiFactorInfo fromList:[self readValue]]; + case 137: + return [PigeonMultiFactorSession fromList:[self readValue]]; + case 138: + return [PigeonPhoneMultiFactorAssertion fromList:[self readValue]]; + case 139: + return [PigeonSignInProvider fromList:[self readValue]]; + case 140: + return [PigeonUserCredential fromList:[self readValue]]; + case 141: + return [PigeonUserDetails fromList:[self readValue]]; + case 142: + return [PigeonUserInfo fromList:[self readValue]]; + case 143: + return [PigeonUserProfile fromList:[self readValue]]; + case 144: + return [PigeonVerifyPhoneNumberRequest fromList:[self readValue]]; + default: + return [super readValueOfType:type]; + } } @end -@implementation PigeonPhoneMultiFactorAssertion -+ (instancetype)makeWithVerificationId:(NSString *)verificationId - verificationCode:(NSString *)verificationCode { - PigeonPhoneMultiFactorAssertion *pigeonResult = [[PigeonPhoneMultiFactorAssertion alloc] init]; - pigeonResult.verificationId = verificationId; - pigeonResult.verificationCode = verificationCode; - return pigeonResult; -} -+ (PigeonPhoneMultiFactorAssertion *)fromMap:(NSDictionary *)dict { - PigeonPhoneMultiFactorAssertion *pigeonResult = [[PigeonPhoneMultiFactorAssertion alloc] init]; - pigeonResult.verificationId = GetNullableObject(dict, @"verificationId"); - NSAssert(pigeonResult.verificationId != nil, @""); - pigeonResult.verificationCode = GetNullableObject(dict, @"verificationCode"); - NSAssert(pigeonResult.verificationCode != nil, @""); - return pigeonResult; -} -+ (nullable PigeonPhoneMultiFactorAssertion *)nullableFromMap:(NSDictionary *)dict { - return (dict) ? [PigeonPhoneMultiFactorAssertion fromMap:dict] : nil; -} -- (NSDictionary *)toMap { - return @{ - @"verificationId" : (self.verificationId ?: [NSNull null]), - @"verificationCode" : (self.verificationCode ?: [NSNull null]), - }; +@interface FirebaseAuthUserHostApiCodecWriter : FlutterStandardWriter +@end +@implementation FirebaseAuthUserHostApiCodecWriter +- (void)writeValue:(id)value { + if ([value isKindOfClass:[PigeonActionCodeInfo class]]) { + [self writeByte:128]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonActionCodeInfoData class]]) { + [self writeByte:129]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonActionCodeSettings class]]) { + [self writeByte:130]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonAdditionalUserInfo class]]) { + [self writeByte:131]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonAuthCredential class]]) { + [self writeByte:132]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonFirebaseApp class]]) { + [self writeByte:133]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonFirebaseAuthSettings class]]) { + [self writeByte:134]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonIdTokenResult class]]) { + [self writeByte:135]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonMultiFactorInfo class]]) { + [self writeByte:136]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonMultiFactorSession class]]) { + [self writeByte:137]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonPhoneMultiFactorAssertion class]]) { + [self writeByte:138]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonSignInProvider class]]) { + [self writeByte:139]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonUserCredential class]]) { + [self writeByte:140]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonUserDetails class]]) { + [self writeByte:141]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonUserInfo class]]) { + [self writeByte:142]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonUserProfile class]]) { + [self writeByte:143]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonVerifyPhoneNumberRequest class]]) { + [self writeByte:144]; + [self writeValue:[value toList]]; + } else { + [super writeValue:value]; + } } @end -@implementation PigeonMultiFactorInfo -+ (instancetype)makeWithDisplayName:(nullable NSString *)displayName - enrollmentTimestamp:(NSNumber *)enrollmentTimestamp - factorId:(nullable NSString *)factorId - uid:(NSString *)uid - phoneNumber:(nullable NSString *)phoneNumber { - PigeonMultiFactorInfo *pigeonResult = [[PigeonMultiFactorInfo alloc] init]; - pigeonResult.displayName = displayName; - pigeonResult.enrollmentTimestamp = enrollmentTimestamp; - pigeonResult.factorId = factorId; - pigeonResult.uid = uid; - pigeonResult.phoneNumber = phoneNumber; - return pigeonResult; -} -+ (PigeonMultiFactorInfo *)fromMap:(NSDictionary *)dict { - PigeonMultiFactorInfo *pigeonResult = [[PigeonMultiFactorInfo alloc] init]; - pigeonResult.displayName = GetNullableObject(dict, @"displayName"); - pigeonResult.enrollmentTimestamp = GetNullableObject(dict, @"enrollmentTimestamp"); - NSAssert(pigeonResult.enrollmentTimestamp != nil, @""); - pigeonResult.factorId = GetNullableObject(dict, @"factorId"); - pigeonResult.uid = GetNullableObject(dict, @"uid"); - NSAssert(pigeonResult.uid != nil, @""); - pigeonResult.phoneNumber = GetNullableObject(dict, @"phoneNumber"); - return pigeonResult; -} -+ (nullable PigeonMultiFactorInfo *)nullableFromMap:(NSDictionary *)dict { - return (dict) ? [PigeonMultiFactorInfo fromMap:dict] : nil; +@interface FirebaseAuthUserHostApiCodecReaderWriter : FlutterStandardReaderWriter +@end +@implementation FirebaseAuthUserHostApiCodecReaderWriter +- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data { + return [[FirebaseAuthUserHostApiCodecWriter alloc] initWithData:data]; } -- (NSDictionary *)toMap { - return @{ - @"displayName" : (self.displayName ?: [NSNull null]), - @"enrollmentTimestamp" : (self.enrollmentTimestamp ?: [NSNull null]), - @"factorId" : (self.factorId ?: [NSNull null]), - @"uid" : (self.uid ?: [NSNull null]), - @"phoneNumber" : (self.phoneNumber ?: [NSNull null]), - }; +- (FlutterStandardReader *)readerWithData:(NSData *)data { + return [[FirebaseAuthUserHostApiCodecReader alloc] initWithData:data]; } @end +NSObject *FirebaseAuthUserHostApiGetCodec(void) { + static FlutterStandardMessageCodec *sSharedObject = nil; + static dispatch_once_t sPred = 0; + dispatch_once(&sPred, ^{ + FirebaseAuthUserHostApiCodecReaderWriter *readerWriter = + [[FirebaseAuthUserHostApiCodecReaderWriter alloc] init]; + sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; + }); + return sSharedObject; +} + +void FirebaseAuthUserHostApiSetup(id binaryMessenger, + NSObject *api) { + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthUserHostApi.delete" + binaryMessenger:binaryMessenger + codec:FirebaseAuthUserHostApiGetCodec()]; + if (api) { + NSCAssert( + [api respondsToSelector:@selector(deleteApp:completion:)], + @"FirebaseAuthUserHostApi api (%@) doesn't respond to @selector(deleteApp:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + [api deleteApp:arg_app + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthUserHostApi.getIdToken" + binaryMessenger:binaryMessenger + codec:FirebaseAuthUserHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(getIdTokenApp:forceRefresh:completion:)], + @"FirebaseAuthUserHostApi api (%@) doesn't respond to " + @"@selector(getIdTokenApp:forceRefresh:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSNumber *arg_forceRefresh = GetNullableObjectAtIndex(args, 1); + [api getIdTokenApp:arg_app + forceRefresh:arg_forceRefresh + completion:^(PigeonIdTokenResult *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthUserHostApi.linkWithCredential" + binaryMessenger:binaryMessenger + codec:FirebaseAuthUserHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(linkWithCredentialApp:input:completion:)], + @"FirebaseAuthUserHostApi api (%@) doesn't respond to " + @"@selector(linkWithCredentialApp:input:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSDictionary *arg_input = GetNullableObjectAtIndex(args, 1); + [api linkWithCredentialApp:arg_app + input:arg_input + completion:^(PigeonUserCredential *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthUserHostApi.linkWithProvider" + binaryMessenger:binaryMessenger + codec:FirebaseAuthUserHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(linkWithProviderApp:signInProvider:completion:)], + @"FirebaseAuthUserHostApi api (%@) doesn't respond to " + @"@selector(linkWithProviderApp:signInProvider:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + PigeonSignInProvider *arg_signInProvider = GetNullableObjectAtIndex(args, 1); + [api linkWithProviderApp:arg_app + signInProvider:arg_signInProvider + completion:^(PigeonUserCredential *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthUserHostApi.reauthenticateWithCredential" + binaryMessenger:binaryMessenger + codec:FirebaseAuthUserHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(reauthenticateWithCredentialApp: + input:completion:)], + @"FirebaseAuthUserHostApi api (%@) doesn't respond to " + @"@selector(reauthenticateWithCredentialApp:input:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSDictionary *arg_input = GetNullableObjectAtIndex(args, 1); + [api reauthenticateWithCredentialApp:arg_app + input:arg_input + completion:^(PigeonUserCredential *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthUserHostApi.reauthenticateWithProvider" + binaryMessenger:binaryMessenger + codec:FirebaseAuthUserHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(reauthenticateWithProviderApp: + signInProvider:completion:)], + @"FirebaseAuthUserHostApi api (%@) doesn't respond to " + @"@selector(reauthenticateWithProviderApp:signInProvider:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + PigeonSignInProvider *arg_signInProvider = GetNullableObjectAtIndex(args, 1); + [api reauthenticateWithProviderApp:arg_app + signInProvider:arg_signInProvider + completion:^(PigeonUserCredential *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthUserHostApi.reload" + binaryMessenger:binaryMessenger + codec:FirebaseAuthUserHostApiGetCodec()]; + if (api) { + NSCAssert( + [api respondsToSelector:@selector(reloadApp:completion:)], + @"FirebaseAuthUserHostApi api (%@) doesn't respond to @selector(reloadApp:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + [api reloadApp:arg_app + completion:^(PigeonUserDetails *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthUserHostApi.sendEmailVerification" + binaryMessenger:binaryMessenger + codec:FirebaseAuthUserHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(sendEmailVerificationApp: + actionCodeSettings:completion:)], + @"FirebaseAuthUserHostApi api (%@) doesn't respond to " + @"@selector(sendEmailVerificationApp:actionCodeSettings:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + PigeonActionCodeSettings *arg_actionCodeSettings = GetNullableObjectAtIndex(args, 1); + [api sendEmailVerificationApp:arg_app + actionCodeSettings:arg_actionCodeSettings + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthUserHostApi.unlink" + binaryMessenger:binaryMessenger + codec:FirebaseAuthUserHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(unlinkApp:providerId:completion:)], + @"FirebaseAuthUserHostApi api (%@) doesn't respond to " + @"@selector(unlinkApp:providerId:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_providerId = GetNullableObjectAtIndex(args, 1); + [api unlinkApp:arg_app + providerId:arg_providerId + completion:^(PigeonUserCredential *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthUserHostApi.updateEmail" + binaryMessenger:binaryMessenger + codec:FirebaseAuthUserHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(updateEmailApp:newEmail:completion:)], + @"FirebaseAuthUserHostApi api (%@) doesn't respond to " + @"@selector(updateEmailApp:newEmail:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_newEmail = GetNullableObjectAtIndex(args, 1); + [api updateEmailApp:arg_app + newEmail:arg_newEmail + completion:^(PigeonUserDetails *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthUserHostApi.updatePassword" + binaryMessenger:binaryMessenger + codec:FirebaseAuthUserHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(updatePasswordApp:newPassword:completion:)], + @"FirebaseAuthUserHostApi api (%@) doesn't respond to " + @"@selector(updatePasswordApp:newPassword:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_newPassword = GetNullableObjectAtIndex(args, 1); + [api updatePasswordApp:arg_app + newPassword:arg_newPassword + completion:^(PigeonUserDetails *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthUserHostApi.updatePhoneNumber" + binaryMessenger:binaryMessenger + codec:FirebaseAuthUserHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(updatePhoneNumberApp:input:completion:)], + @"FirebaseAuthUserHostApi api (%@) doesn't respond to " + @"@selector(updatePhoneNumberApp:input:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSDictionary *arg_input = GetNullableObjectAtIndex(args, 1); + [api updatePhoneNumberApp:arg_app + input:arg_input + completion:^(PigeonUserDetails *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthUserHostApi.updateProfile" + binaryMessenger:binaryMessenger + codec:FirebaseAuthUserHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(updateProfileApp:profile:completion:)], + @"FirebaseAuthUserHostApi api (%@) doesn't respond to " + @"@selector(updateProfileApp:profile:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + PigeonUserProfile *arg_profile = GetNullableObjectAtIndex(args, 1); + [api + updateProfileApp:arg_app + profile:arg_profile + completion:^(PigeonUserDetails *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.FirebaseAuthUserHostApi.verifyBeforeUpdateEmail" + binaryMessenger:binaryMessenger + codec:FirebaseAuthUserHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector + (verifyBeforeUpdateEmailApp:newEmail:actionCodeSettings:completion:)], + @"FirebaseAuthUserHostApi api (%@) doesn't respond to " + @"@selector(verifyBeforeUpdateEmailApp:newEmail:actionCodeSettings:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_newEmail = GetNullableObjectAtIndex(args, 1); + PigeonActionCodeSettings *arg_actionCodeSettings = GetNullableObjectAtIndex(args, 2); + [api verifyBeforeUpdateEmailApp:arg_app + newEmail:arg_newEmail + actionCodeSettings:arg_actionCodeSettings + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } +} @interface MultiFactorUserHostApiCodecReader : FlutterStandardReader @end @implementation MultiFactorUserHostApiCodecReader - (nullable id)readValueOfType:(UInt8)type { switch (type) { case 128: - return [PigeonMultiFactorInfo fromMap:[self readValue]]; - + return [PigeonFirebaseApp fromList:[self readValue]]; case 129: - return [PigeonMultiFactorSession fromMap:[self readValue]]; - + return [PigeonMultiFactorInfo fromList:[self readValue]]; case 130: - return [PigeonPhoneMultiFactorAssertion fromMap:[self readValue]]; - + return [PigeonMultiFactorSession fromList:[self readValue]]; + case 131: + return [PigeonPhoneMultiFactorAssertion fromList:[self readValue]]; default: return [super readValueOfType:type]; } @@ -162,15 +1887,18 @@ @interface MultiFactorUserHostApiCodecWriter : FlutterStandardWriter @end @implementation MultiFactorUserHostApiCodecWriter - (void)writeValue:(id)value { - if ([value isKindOfClass:[PigeonMultiFactorInfo class]]) { + if ([value isKindOfClass:[PigeonFirebaseApp class]]) { [self writeByte:128]; - [self writeValue:[value toMap]]; - } else if ([value isKindOfClass:[PigeonMultiFactorSession class]]) { + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonMultiFactorInfo class]]) { [self writeByte:129]; - [self writeValue:[value toMap]]; - } else if ([value isKindOfClass:[PigeonPhoneMultiFactorAssertion class]]) { + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonMultiFactorSession class]]) { [self writeByte:130]; - [self writeValue:[value toMap]]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonPhoneMultiFactorAssertion class]]) { + [self writeByte:131]; + [self writeValue:[value toList]]; } else { [super writeValue:value]; } @@ -188,9 +1916,9 @@ - (FlutterStandardReader *)readerWithData:(NSData *)data { } @end -NSObject *MultiFactorUserHostApiGetCodec() { - static dispatch_once_t sPred = 0; +NSObject *MultiFactorUserHostApiGetCodec(void) { static FlutterStandardMessageCodec *sSharedObject = nil; + static dispatch_once_t sPred = 0; dispatch_once(&sPred, ^{ MultiFactorUserHostApiCodecReaderWriter *readerWriter = [[MultiFactorUserHostApiCodecReaderWriter alloc] init]; @@ -207,22 +1935,22 @@ void MultiFactorUserHostApiSetup(id binaryMessenger, binaryMessenger:binaryMessenger codec:MultiFactorUserHostApiGetCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(enrollPhoneAppName: - assertion:displayName:completion:)], + NSCAssert([api respondsToSelector:@selector(enrollPhoneApp: + assertion:displayName:completion:)], @"MultiFactorUserHostApi api (%@) doesn't respond to " - @"@selector(enrollPhoneAppName:assertion:displayName:completion:)", + @"@selector(enrollPhoneApp:assertion:displayName:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; - NSString *arg_appName = GetNullableObjectAtIndex(args, 0); + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); PigeonPhoneMultiFactorAssertion *arg_assertion = GetNullableObjectAtIndex(args, 1); NSString *arg_displayName = GetNullableObjectAtIndex(args, 2); - [api enrollPhoneAppName:arg_appName - assertion:arg_assertion - displayName:arg_displayName - completion:^(FlutterError *_Nullable error) { - callback(wrapResult(nil, error)); - }]; + [api enrollPhoneApp:arg_app + assertion:arg_assertion + displayName:arg_displayName + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; }]; } else { [channel setMessageHandler:nil]; @@ -234,18 +1962,18 @@ void MultiFactorUserHostApiSetup(id binaryMessenger, binaryMessenger:binaryMessenger codec:MultiFactorUserHostApiGetCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(getSessionAppName:completion:)], + NSCAssert([api respondsToSelector:@selector(getSessionApp:completion:)], @"MultiFactorUserHostApi api (%@) doesn't respond to " - @"@selector(getSessionAppName:completion:)", + @"@selector(getSessionApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; - NSString *arg_appName = GetNullableObjectAtIndex(args, 0); - [api getSessionAppName:arg_appName - completion:^(PigeonMultiFactorSession *_Nullable output, - FlutterError *_Nullable error) { - callback(wrapResult(output, error)); - }]; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + [api getSessionApp:arg_app + completion:^(PigeonMultiFactorSession *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; }]; } else { [channel setMessageHandler:nil]; @@ -257,19 +1985,19 @@ void MultiFactorUserHostApiSetup(id binaryMessenger, binaryMessenger:binaryMessenger codec:MultiFactorUserHostApiGetCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(unenrollAppName:factorUid:completion:)], + NSCAssert([api respondsToSelector:@selector(unenrollApp:factorUid:completion:)], @"MultiFactorUserHostApi api (%@) doesn't respond to " - @"@selector(unenrollAppName:factorUid:completion:)", + @"@selector(unenrollApp:factorUid:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; - NSString *arg_appName = GetNullableObjectAtIndex(args, 0); + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_factorUid = GetNullableObjectAtIndex(args, 1); - [api unenrollAppName:arg_appName - factorUid:arg_factorUid - completion:^(FlutterError *_Nullable error) { - callback(wrapResult(nil, error)); - }]; + [api unenrollApp:arg_app + factorUid:arg_factorUid + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; }]; } else { [channel setMessageHandler:nil]; @@ -281,18 +2009,18 @@ void MultiFactorUserHostApiSetup(id binaryMessenger, binaryMessenger:binaryMessenger codec:MultiFactorUserHostApiGetCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(getEnrolledFactorsAppName:completion:)], + NSCAssert([api respondsToSelector:@selector(getEnrolledFactorsApp:completion:)], @"MultiFactorUserHostApi api (%@) doesn't respond to " - @"@selector(getEnrolledFactorsAppName:completion:)", + @"@selector(getEnrolledFactorsApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; - NSString *arg_appName = GetNullableObjectAtIndex(args, 0); - [api getEnrolledFactorsAppName:arg_appName - completion:^(NSArray *_Nullable output, - FlutterError *_Nullable error) { - callback(wrapResult(output, error)); - }]; + PigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + [api getEnrolledFactorsApp:arg_app + completion:^(NSArray *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; }]; } else { [channel setMessageHandler:nil]; @@ -305,14 +2033,17 @@ @implementation MultiFactoResolverHostApiCodecReader - (nullable id)readValueOfType:(UInt8)type { switch (type) { case 128: - return [PigeonMultiFactorInfo fromMap:[self readValue]]; - + return [PigeonAdditionalUserInfo fromList:[self readValue]]; case 129: - return [PigeonMultiFactorSession fromMap:[self readValue]]; - + return [PigeonAuthCredential fromList:[self readValue]]; case 130: - return [PigeonPhoneMultiFactorAssertion fromMap:[self readValue]]; - + return [PigeonPhoneMultiFactorAssertion fromList:[self readValue]]; + case 131: + return [PigeonUserCredential fromList:[self readValue]]; + case 132: + return [PigeonUserDetails fromList:[self readValue]]; + case 133: + return [PigeonUserInfo fromList:[self readValue]]; default: return [super readValueOfType:type]; } @@ -323,15 +2054,24 @@ @interface MultiFactoResolverHostApiCodecWriter : FlutterStandardWriter @end @implementation MultiFactoResolverHostApiCodecWriter - (void)writeValue:(id)value { - if ([value isKindOfClass:[PigeonMultiFactorInfo class]]) { + if ([value isKindOfClass:[PigeonAdditionalUserInfo class]]) { [self writeByte:128]; - [self writeValue:[value toMap]]; - } else if ([value isKindOfClass:[PigeonMultiFactorSession class]]) { + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonAuthCredential class]]) { [self writeByte:129]; - [self writeValue:[value toMap]]; + [self writeValue:[value toList]]; } else if ([value isKindOfClass:[PigeonPhoneMultiFactorAssertion class]]) { [self writeByte:130]; - [self writeValue:[value toMap]]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonUserCredential class]]) { + [self writeByte:131]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonUserDetails class]]) { + [self writeByte:132]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonUserInfo class]]) { + [self writeByte:133]; + [self writeValue:[value toList]]; } else { [super writeValue:value]; } @@ -349,9 +2089,9 @@ - (FlutterStandardReader *)readerWithData:(NSData *)data { } @end -NSObject *MultiFactoResolverHostApiGetCodec() { - static dispatch_once_t sPred = 0; +NSObject *MultiFactoResolverHostApiGetCodec(void) { static FlutterStandardMessageCodec *sSharedObject = nil; + static dispatch_once_t sPred = 0; dispatch_once(&sPred, ^{ MultiFactoResolverHostApiCodecReaderWriter *readerWriter = [[MultiFactoResolverHostApiCodecReaderWriter alloc] init]; @@ -378,7 +2118,7 @@ void MultiFactoResolverHostApiSetup(id binaryMessenger, PigeonPhoneMultiFactorAssertion *arg_assertion = GetNullableObjectAtIndex(args, 1); [api resolveSignInResolverId:arg_resolverId assertion:arg_assertion - completion:^(NSDictionary *_Nullable output, + completion:^(PigeonUserCredential *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -394,8 +2134,7 @@ @implementation GenerateInterfacesCodecReader - (nullable id)readValueOfType:(UInt8)type { switch (type) { case 128: - return [PigeonMultiFactorInfo fromMap:[self readValue]]; - + return [PigeonMultiFactorInfo fromList:[self readValue]]; default: return [super readValueOfType:type]; } @@ -408,7 +2147,7 @@ @implementation GenerateInterfacesCodecWriter - (void)writeValue:(id)value { if ([value isKindOfClass:[PigeonMultiFactorInfo class]]) { [self writeByte:128]; - [self writeValue:[value toMap]]; + [self writeValue:[value toList]]; } else { [super writeValue:value]; } @@ -426,9 +2165,9 @@ - (FlutterStandardReader *)readerWithData:(NSData *)data { } @end -NSObject *GenerateInterfacesGetCodec() { - static dispatch_once_t sPred = 0; +NSObject *GenerateInterfacesGetCodec(void) { static FlutterStandardMessageCodec *sSharedObject = nil; + static dispatch_once_t sPred = 0; dispatch_once(&sPred, ^{ GenerateInterfacesCodecReaderWriter *readerWriter = [[GenerateInterfacesCodecReaderWriter alloc] init]; diff --git a/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart b/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart index 22f0f226e4b0..e90727628de5 100644 --- a/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart @@ -417,18 +417,19 @@ class FirebaseAuth extends FirebasePluginPlatform { /// settings > Capabilities). To learn more, visit the /// [Apple documentation](https://developer.apple.com/documentation/security/keychain_services/keychain_items/sharing_access_to_keychain_items_among_a_collection_of_apps). Future setSettings({ - bool? appVerificationDisabledForTesting, + bool appVerificationDisabledForTesting = false, String? userAccessGroup, String? phoneNumber, String? smsCode, bool? forceRecaptchaFlow, }) { return _delegate.setSettings( - appVerificationDisabledForTesting: appVerificationDisabledForTesting, - userAccessGroup: userAccessGroup, - phoneNumber: phoneNumber, - smsCode: smsCode, - forceRecaptchaFlow: forceRecaptchaFlow); + appVerificationDisabledForTesting: appVerificationDisabledForTesting, + userAccessGroup: userAccessGroup, + phoneNumber: phoneNumber, + smsCode: smsCode, + forceRecaptchaFlow: forceRecaptchaFlow, + ); } /// Changes the current type of persistence on the current Auth instance for diff --git a/packages/firebase_auth/firebase_auth/lib/src/user.dart b/packages/firebase_auth/firebase_auth/lib/src/user.dart index 66280bf49fdc..f87194345910 100644 --- a/packages/firebase_auth/firebase_auth/lib/src/user.dart +++ b/packages/firebase_auth/firebase_auth/lib/src/user.dart @@ -37,7 +37,7 @@ class User { /// Once verified, call [reload] to ensure the latest user information is /// retrieved from Firebase. bool get emailVerified { - return _delegate.emailVerified; + return _delegate.isEmailVerified; } /// Returns whether the user is a anonymous. @@ -116,7 +116,7 @@ class User { /// /// If [forceRefresh] is `true`, the token returned will be refreshed regardless /// of token expiration. - Future getIdToken([bool forceRefresh = false]) { + Future getIdToken([bool forceRefresh = false]) { return _delegate.getIdToken(forceRefresh); } @@ -671,7 +671,7 @@ class User { return '$User(' 'displayName: $displayName, ' 'email: $email, ' - 'emailVerified: $emailVerified, ' + 'isEmailVerified: $emailVerified, ' 'isAnonymous: $isAnonymous, ' 'metadata: $metadata, ' 'phoneNumber: $phoneNumber, ' diff --git a/packages/firebase_auth/firebase_auth/macos/Classes/PigeonParser.m b/packages/firebase_auth/firebase_auth/macos/Classes/PigeonParser.m new file mode 120000 index 000000000000..03530737fc03 --- /dev/null +++ b/packages/firebase_auth/firebase_auth/macos/Classes/PigeonParser.m @@ -0,0 +1 @@ +../../ios/Classes/PigeonParser.m \ No newline at end of file diff --git a/packages/firebase_auth/firebase_auth/macos/Classes/Private/PigeonParser.h b/packages/firebase_auth/firebase_auth/macos/Classes/Private/PigeonParser.h new file mode 120000 index 000000000000..58ed1a9d3d08 --- /dev/null +++ b/packages/firebase_auth/firebase_auth/macos/Classes/Private/PigeonParser.h @@ -0,0 +1 @@ +../../../ios/Classes/Private/PigeonParser.h \ No newline at end of file diff --git a/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart b/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart index e54a246fb37f..04f71f5bb1c0 100644 --- a/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart +++ b/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart @@ -43,24 +43,25 @@ void main() { final int kMockLastSignInTimestamp = DateTime.now().subtract(const Duration(days: 1)).millisecondsSinceEpoch; - Map kMockUser = { - 'isAnonymous': true, - 'emailVerified': false, - 'displayName': 'displayName', - 'metadata': { - 'creationTime': kMockCreationTimestamp, - 'lastSignInTime': kMockLastSignInTimestamp, - }, - 'providerData': >[ - { + final kMockUser = PigeonUserDetails( + userInfo: PigeonUserInfo( + uid: '12345', + displayName: 'displayName', + creationTimestamp: kMockCreationTimestamp, + lastSignInTimestamp: kMockLastSignInTimestamp, + isAnonymous: true, + isEmailVerified: false, + ), + providerData: [ + { 'providerId': 'firebase', 'uid': '12345', 'displayName': 'Flutter Test User', - 'photoURL': 'http://www.example.com/', + 'photoUrl': 'http://www.example.com/', 'email': 'test@example.com', - }, + } ], - }; + ); MockUserPlatform? mockUserPlatform; MockUserCredentialPlatform? mockUserCredPlatform; @@ -72,7 +73,7 @@ void main() { MockFirebaseAuth mockAuthPlatform = MockFirebaseAuth(); group('$FirebaseAuth', () { - Map user; + PigeonUserDetails user; // used to generate a unique application name for each test var testCount = 0; @@ -247,8 +248,12 @@ void main() { group('checkActionCode()', () { test('should call delegate method', () async { // Necessary as we otherwise get a "null is not a Future" error - when(mockAuthPlatform.checkActionCode(any)) - .thenAnswer((i) async => ActionCodeInfo(data: {}, operation: 0)); + when(mockAuthPlatform.checkActionCode(any)).thenAnswer( + (i) async => ActionCodeInfo( + data: ActionCodeInfoData(email: null, previousEmail: null), + operation: ActionCodeInfoOperation.unknown, + ), + ); await auth.checkActionCode(kMockActionCode); verify(mockAuthPlatform.checkActionCode(kMockActionCode)); @@ -377,7 +382,7 @@ void main() { final ActionCodeSettings kMockActionCodeSettingsNull = ActionCodeSettings(url: kMockURL); final ActionCodeSettings kMockActionCodeSettingsFalse = - ActionCodeSettings(url: kMockURL, handleCodeInApp: false); + ActionCodeSettings(url: kMockURL); // when handleCodeInApp is null expect( @@ -840,7 +845,7 @@ class MockFirebaseAuth extends Mock @override FirebaseAuthPlatform setInitialValues({ - Map? currentUser, + PigeonUserDetails? currentUser, String? languageCode, }) { return super.noSuchMethod( @@ -1034,7 +1039,7 @@ class FakeFirebaseAuthPlatform extends Fake @override FirebaseAuthPlatform setInitialValues({ - Map? currentUser, + PigeonUserDetails? currentUser, String? languageCode, }) { return this; @@ -1045,7 +1050,7 @@ class MockUserPlatform extends Mock with MockPlatformInterfaceMixin implements TestUserPlatform { MockUserPlatform(FirebaseAuthPlatform auth, MultiFactorPlatform multiFactor, - Map _user) { + PigeonUserDetails _user) { TestUserPlatform(auth, multiFactor, _user); } } @@ -1096,7 +1101,7 @@ class TestFirebaseAuthPlatform extends FirebaseAuthPlatform { @override FirebaseAuthPlatform setInitialValues({ - Map? currentUser, + PigeonUserDetails? currentUser, String? languageCode, }) { return this; @@ -1165,7 +1170,7 @@ class TestAuthProvider extends AuthProvider { class TestUserPlatform extends UserPlatform { TestUserPlatform(FirebaseAuthPlatform auth, MultiFactorPlatform multiFactor, - Map data) + PigeonUserDetails data) : super(auth, multiFactor, data); } diff --git a/packages/firebase_auth/firebase_auth/test/user_test.dart b/packages/firebase_auth/firebase_auth/test/user_test.dart index 9aca8c0e3fe9..6b5ebae89521 100644 --- a/packages/firebase_auth/firebase_auth/test/user_test.dart +++ b/packages/firebase_auth/firebase_auth/test/user_test.dart @@ -31,42 +31,43 @@ void main() { FirebaseAuth? auth; - const Map kMockIdTokenResult = { - 'token': '12345', - 'expirationTimestamp': 123456, - 'authTimestamp': 1234567, - 'issuedAtTimestamp': 12345678, - 'signInProvider': 'password', - 'claims': { + final kMockIdTokenResult = PigeonIdTokenResult( + token: '12345', + expirationTimestamp: 123456, + authTimestamp: 1234567, + issuedAtTimestamp: 12345678, + signInProvider: 'password', + claims: { 'claim1': 'value1', }, - }; + ); final int kMockCreationTimestamp = DateTime.now().subtract(const Duration(days: 2)).millisecondsSinceEpoch; final int kMockLastSignInTimestamp = DateTime.now().subtract(const Duration(days: 1)).millisecondsSinceEpoch; - Map kMockUser = { - 'isAnonymous': true, - 'emailVerified': false, - 'uid': '42', - 'displayName': 'displayName', - 'metadata': { - 'creationTime': kMockCreationTimestamp, - 'lastSignInTime': kMockLastSignInTimestamp, - }, - 'providerData': >[ - { + final kMockUser = PigeonUserDetails( + userInfo: PigeonUserInfo( + uid: '12345', + displayName: 'displayName', + creationTimestamp: kMockCreationTimestamp, + lastSignInTimestamp: kMockLastSignInTimestamp, + isAnonymous: true, + isEmailVerified: false, + ), + providerData: [ + { 'providerId': 'firebase', 'uid': '12345', 'displayName': 'Flutter Test User', - 'photoURL': 'http://www.example.com/', + 'photoUrl': null, 'email': 'test@example.com', - }, + 'isAnonymous': true, + 'isEmailVerified': false, + } ], - }; - + ); MockUserPlatform? mockUserPlatform; MockUserCredentialPlatform? mockUserCredPlatform; @@ -84,7 +85,7 @@ void main() { var mockAuthPlatform = MockFirebaseAuth(); group('$User', () { - Map? user; + PigeonUserDetails? user; // used to generate a unique application name for each test var testCount = 0; @@ -330,7 +331,7 @@ void main() { 'displayName: Flutter Test User, ' 'email: test@example.com, ' 'phoneNumber: null, ' - 'photoURL: http://www.example.com/, ' + 'photoURL: null, ' 'providerId: firebase, ' 'uid: 12345)'; @@ -343,7 +344,7 @@ void main() { 'User(' 'displayName: displayName, ' 'email: null, ' - 'emailVerified: false, ' + 'isEmailVerified: false, ' 'isAnonymous: true, ' 'metadata: $userMetadata, ' 'phoneNumber: null, ' @@ -352,7 +353,7 @@ void main() { '[$userInfo], ' 'refreshToken: null, ' 'tenantId: null, ' - 'uid: 42)', + 'uid: 12345)', ); }); }); @@ -387,7 +388,7 @@ class MockFirebaseAuth extends Mock @override FirebaseAuthPlatform setInitialValues({ - Map? currentUser, + PigeonUserDetails? currentUser, String? languageCode, }) { return super.noSuchMethod( @@ -404,7 +405,7 @@ class MockFirebaseAuth extends Mock class MockUserPlatform extends Mock with MockPlatformInterfaceMixin implements TestUserPlatform { - MockUserPlatform(FirebaseAuthPlatform auth, Map _user) { + MockUserPlatform(FirebaseAuthPlatform auth, PigeonUserDetails _user) { TestUserPlatform(auth, TestMultiFactorPlatform(auth), _user); } @@ -564,7 +565,7 @@ class TestFirebaseAuthPlatform extends FirebaseAuthPlatform { @override FirebaseAuthPlatform setInitialValues({ - Map? currentUser, + PigeonUserDetails? currentUser, String? languageCode, }) { return this; @@ -573,7 +574,7 @@ class TestFirebaseAuthPlatform extends FirebaseAuthPlatform { class TestUserPlatform extends UserPlatform { TestUserPlatform(FirebaseAuthPlatform auth, MultiFactorPlatform multiFactor, - Map data) + PigeonUserDetails data) : super(auth, multiFactor, data); } diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/firebase_auth_platform_interface.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/firebase_auth_platform_interface.dart index 34267a6e6248..7201da59cdcf 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/firebase_auth_platform_interface.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/firebase_auth_platform_interface.dart @@ -13,6 +13,12 @@ export 'src/auth_provider.dart'; export 'src/firebase_auth_exception.dart'; export 'src/firebase_auth_multi_factor_exception.dart'; export 'src/id_token_result.dart'; +export 'src/pigeon/messages.pigeon.dart' + show + PigeonUserDetails, + PigeonUserInfo, + ActionCodeInfoOperation, + PigeonIdTokenResult; export 'src/platform_interface/platform_interface_confirmation_result.dart'; export 'src/platform_interface/platform_interface_firebase_auth.dart'; export 'src/platform_interface/platform_interface_multi_factor.dart'; diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/action_code_info.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/action_code_info.dart index 512718fc7c8d..64aeb5aa48ad 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/action_code_info.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/action_code_info.dart @@ -3,77 +3,48 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart'; import 'package:meta/meta.dart'; -/// The type of operation that generated the action code from calling -/// [checkActionCode]. -enum ActionCodeInfoOperation { - /// Unknown operation. - unknown, - - /// Password reset code generated via [sendPasswordResetEmail]. - passwordReset, - - /// Email verification code generated via [User.sendEmailVerification]. - verifyEmail, - - /// Email change revocation code generated via [User.updateEmail]. - recoverEmail, +/// A response from calling [checkActionCode]. +class ActionCodeInfo { + // ignore: public_member_api_docs + @protected + ActionCodeInfo({ + required this.operation, + required ActionCodeInfoData data, + }) : _data = data; - /// Email sign in code generated via [sendSignInLinkToEmail]. - emailSignIn, + ActionCodeInfoOperation operation; - /// Verify and change email code generated via [User.verifyBeforeUpdateEmail]. - verifyAndChangeEmail, + ActionCodeInfoData _data; - /// Action code for reverting second factor addition. - revertSecondFactorAddition, + Map get data => _data.toMap(); } -/// A response from calling [checkActionCode]. -class ActionCodeInfo { +/// The data associated with the action code. +/// +/// Depending on the [ActionCodeInfoOperation], `email` and `previousEmail` +/// may be available. +class ActionCodeInfoData { // ignore: public_member_api_docs @protected - ActionCodeInfo({ - required int operation, - required Map data, - }) : _operation = operation, - _data = data; - - int _operation; + ActionCodeInfoData({ + required this.email, + required this.previousEmail, + }); - Map _data; + /// The email associated with the action code. + final String? email; - /// The type of operation that generated the action code. - ActionCodeInfoOperation get operation { - switch (_operation) { - case 0: - return ActionCodeInfoOperation.unknown; - case 1: - return ActionCodeInfoOperation.passwordReset; - case 2: - return ActionCodeInfoOperation.verifyEmail; - case 3: - return ActionCodeInfoOperation.recoverEmail; - case 4: - return ActionCodeInfoOperation.emailSignIn; - case 5: - return ActionCodeInfoOperation.verifyAndChangeEmail; - case 6: - return ActionCodeInfoOperation.revertSecondFactorAddition; - default: - throw UnsupportedError('Unknown ActionCodeInfoOperation: $_operation.'); - } - } + /// The previous email associated with the action code. + final String? previousEmail; - /// The data associated with the action code. - /// - /// Depending on the [ActionCodeInfoOperation], `email` and `previousEmail` - /// may be available. - Map get data { + /// Converts the [ActionCodeInfoData] instance to a [Map]. + Map toMap() { return { - 'email': _data['email'], - 'previousEmail': _data['previousEmail'], + 'email': email, + 'previousEmail': previousEmail, }; } } diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/action_code_settings.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/action_code_settings.dart index 6c81f87cc46b..c82aa222f041 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/action_code_settings.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/action_code_settings.dart @@ -13,9 +13,9 @@ class ActionCodeSettings { ActionCodeSettings({ this.androidPackageName, this.androidMinimumVersion, - this.androidInstallApp, + this.androidInstallApp = false, this.dynamicLinkDomain, - this.handleCodeInApp, + this.handleCodeInApp = false, this.iOSBundleId, required this.url, }); @@ -30,9 +30,9 @@ class ActionCodeSettings { /// one specified they will be taken to the Play Store to upgrade the application. final String? androidMinimumVersion; - /// Whether or not the user should be automatically prompted to install the app + /// The default is false. Whether or not the user should be automatically prompted to install the app /// via the Play Store if it is not already installed. - final bool? androidInstallApp; + final bool androidInstallApp; /// The iOS app to open if it is installed on the device. final String? iOSBundleId; @@ -43,7 +43,7 @@ class ActionCodeSettings { /// The default is false. When true, the action code link will be sent /// as a Universal Link or Android App Link and will be opened by the /// app if installed. - final bool? handleCodeInApp; + final bool handleCodeInApp; /// Sets the link continue/state URL final String url; diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/id_token_result.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/id_token_result.dart index 5fec5b46bef1..48b0ffb224dd 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/id_token_result.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/id_token_result.dart @@ -3,6 +3,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart'; import 'package:meta/meta.dart'; /// Interface representing ID token result obtained from [getIdTokenResult]. @@ -18,36 +19,35 @@ class IdTokenResult { @protected IdTokenResult(this._data); - final Map _data; + final PigeonIdTokenResult _data; /// The authentication time formatted as UTC string. This is the time the user /// authenticated (signed in) and not the time the token was refreshed. - DateTime? get authTime => _data['authTimestamp'] == null + DateTime? get authTime => _data.authTimestamp == null ? null - : DateTime.fromMillisecondsSinceEpoch(_data['authTimestamp']); + : DateTime.fromMillisecondsSinceEpoch(_data.authTimestamp!); /// The entire payload claims of the ID token including the standard reserved /// claims as well as the custom claims. - Map? get claims => _data['claims'] == null - ? null - : Map.from(_data['claims']); + Map? get claims => + _data.claims == null ? null : Map.from(_data.claims!); /// The time when the ID token expires. - DateTime? get expirationTime => _data['expirationTimestamp'] == null + DateTime? get expirationTime => _data.expirationTimestamp == null ? null - : DateTime.fromMillisecondsSinceEpoch(_data['expirationTimestamp']); + : DateTime.fromMillisecondsSinceEpoch(_data.expirationTimestamp!); /// The time when ID token was issued. - DateTime? get issuedAtTime => _data['issuedAtTimestamp'] == null + DateTime? get issuedAtTime => _data.issuedAtTimestamp == null ? null - : DateTime.fromMillisecondsSinceEpoch(_data['issuedAtTimestamp']); + : DateTime.fromMillisecondsSinceEpoch(_data.issuedAtTimestamp!); /// The sign-in provider through which the ID token was obtained (anonymous, /// custom, phone, password, etc). Note, this does not map to provider IDs. - String? get signInProvider => _data['signInProvider']; + String? get signInProvider => _data.signInProvider; /// The Firebase Auth ID token JWT string. - String? get token => _data['token']; + String? get token => _data.token; @override String toString() { diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart index 8c95a9ae4d86..5ae3b642d293 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart @@ -4,11 +4,12 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:io' show Platform; import 'package:_flutterfire_internals/_flutterfire_internals.dart'; +import 'package:collection/collection.dart'; import 'package:firebase_auth_platform_interface/src/method_channel/method_channel_multi_factor.dart'; import 'package:firebase_auth_platform_interface/src/method_channel/utils/convert_auth_provider.dart'; +import 'package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; @@ -25,6 +26,8 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { 'plugins.flutter.io/firebase_auth', ); + final _api = FirebaseAuthHostApi(); + /// Map of [MethodChannelFirebaseAuth] that can be get with Firebase App Name. static Map methodChannelFirebaseAuthInstances = @@ -55,6 +58,13 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { return MethodChannelFirebaseAuth._(); } + PigeonFirebaseApp get pigeonDefault { + return PigeonFirebaseApp( + appName: app.name, + tenantId: tenantId, + ); + } + /// Internal stub class initializer. /// /// When the user code calls an auth method, the real instance is @@ -64,10 +74,8 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { /// Creates a new instance with a given [FirebaseApp]. MethodChannelFirebaseAuth({required FirebaseApp app}) : super(appInstance: app) { - channel.invokeMethod('Auth#registerIdTokenListener', { - 'appName': app.name, - }).then((channelName) { - final events = EventChannel(channelName!, channel.codec); + _api.registerIdTokenListener(pigeonDefault).then((channelName) { + final events = EventChannel(channelName, channel.codec); events .receiveGuardedBroadcastStream(onError: convertPlatformException) .listen( @@ -77,10 +85,8 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { ); }); - channel.invokeMethod('Auth#registerAuthStateListener', { - 'appName': app.name, - }).then((channelName) { - final events = EventChannel(channelName!, channel.codec); + _api.registerAuthStateListener(pigeonDefault).then((channelName) { + final events = EventChannel(channelName, channel.codec); events .receiveGuardedBroadcastStream(onError: convertPlatformException) .listen( @@ -135,9 +141,8 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { streamController.add(const _ValueWrapper.absent()); } else { final MethodChannelUser user = MethodChannelUser( - instance, multiFactorInstance, userMap.cast()); + instance, multiFactorInstance, PigeonUserDetails.decode(userMap)); - // TODO(rousselGit): should this logic be moved to the setter instead? instance.currentUser = user; streamController.add(_ValueWrapper(instance.currentUser)); } @@ -171,23 +176,14 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { userChangesStreamController.add(const _ValueWrapper.absent()); } else { final MethodChannelUser user = MethodChannelUser( - instance, multiFactorInstance, userMap.cast()); + instance, multiFactorInstance, PigeonUserDetails.decode(userMap)); - // TODO(rousselGit): should this logic be moved to the setter instead? instance.currentUser = user; idTokenStreamController.add(_ValueWrapper(user)); userChangesStreamController.add(_ValueWrapper(user)); } } - /// Attaches generic default values to method channel arguments. - Map _withChannelDefaults(Map other) { - return { - 'appName': app.name, - 'tenantId': tenantId, - }..addAll(other); - } - /// Gets a [FirebaseAuthPlatform] with specific arguments such as a different /// [FirebaseApp]. /// @@ -202,7 +198,7 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { @override MethodChannelFirebaseAuth setInitialValues({ - Map? currentUser, + PigeonUserDetails? currentUser, String? languageCode, }) { if (currentUser != null) { @@ -217,12 +213,7 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { @override Future useAuthEmulator(String host, int port) async { try { - await channel.invokeMethod( - 'Auth#useEmulator', - _withChannelDefaults({ - 'host': host, - 'port': port, - })); + await _api.useEmulator(pigeonDefault, host, port); } catch (e, stack) { convertPlatformException(e, stack); } @@ -231,11 +222,7 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { @override Future applyActionCode(String code) async { try { - await channel.invokeMethod( - 'Auth#applyActionCode', - _withChannelDefaults({ - 'code': code, - })); + await _api.applyActionCode(pigeonDefault, code); } catch (e, stack) { convertPlatformException(e, stack); } @@ -244,16 +231,14 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { @override Future checkActionCode(String code) async { try { - Map result = - (await channel.invokeMapMethod( - 'Auth#checkActionCode', - _withChannelDefaults({ - 'code': code, - })))!; + final result = await _api.checkActionCode(pigeonDefault, code); return ActionCodeInfo( - operation: result['operation'], - data: Map.from(result['data']), + operation: result.operation, + data: ActionCodeInfoData( + email: result.data.email, + previousEmail: result.data.previousEmail, + ), ); } catch (e, stack) { convertPlatformException(e, stack); @@ -263,12 +248,7 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { @override Future confirmPasswordReset(String code, String newPassword) async { try { - await channel.invokeMethod( - 'Auth#confirmPasswordReset', - _withChannelDefaults({ - 'code': code, - 'newPassword': newPassword, - })); + await _api.confirmPasswordReset(pigeonDefault, code, newPassword); } catch (e, stack) { convertPlatformException(e, stack); } @@ -278,16 +258,13 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { Future createUserWithEmailAndPassword( String email, String password) async { try { - Map data = - (await channel.invokeMapMethod( - 'Auth#createUserWithEmailAndPassword', - _withChannelDefaults({ - 'email': email, - 'password': password, - })))!; - + final result = await _api.createUserWithEmailAndPassword( + pigeonDefault, + email, + password, + ); MethodChannelUserCredential userCredential = - MethodChannelUserCredential(this, data); + MethodChannelUserCredential(this, result); currentUser = userCredential.user; return userCredential; @@ -297,151 +274,32 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { } @override - Future> fetchSignInMethodsForEmail(String email) async { + Future signInAnonymously() async { try { - Map data = - (await channel.invokeMapMethod( - 'Auth#fetchSignInMethodsForEmail', - _withChannelDefaults({ - 'email': email, - })))!; - - return List.from(data['providers']); - } catch (e, stack) { - convertPlatformException(e, stack); - } - } - - @override - Stream authStateChanges() async* { - yield currentUser; - yield* _authStateChangesListeners[app.name]! - .stream - .map((event) => event.value); - } - - @override - Stream idTokenChanges() async* { - yield currentUser; - yield* _idTokenChangesListeners[app.name]! - .stream - .map((event) => event.value); - } + final result = await _api.signInAnonymously(pigeonDefault); - @override - Stream userChanges() async* { - yield currentUser; - yield* _userChangesListeners[app.name]!.stream.map((event) => event.value); - } + MethodChannelUserCredential userCredential = + MethodChannelUserCredential(this, result); - @override - Future sendPasswordResetEmail( - String email, [ - ActionCodeSettings? actionCodeSettings, - ]) async { - try { - await channel.invokeMethod( - 'Auth#sendPasswordResetEmail', - _withChannelDefaults({ - 'email': email, - 'actionCodeSettings': actionCodeSettings?.asMap(), - })); + currentUser = userCredential.user; + return userCredential; } catch (e, stack) { convertPlatformException(e, stack); } } @override - Future sendSignInLinkToEmail( - String email, - ActionCodeSettings actionCodeSettings, + Future signInWithCredential( + AuthCredential credential, ) async { try { - await channel.invokeMethod( - 'Auth#sendSignInLinkToEmail', - _withChannelDefaults({ - 'email': email, - 'actionCodeSettings': actionCodeSettings.asMap(), - })); - } catch (e, stack) { - convertPlatformException(e, stack); - } - } - - @override - Future setLanguageCode(String? languageCode) async { - try { - Map data = - (await channel.invokeMapMethod( - 'Auth#setLanguageCode', - _withChannelDefaults({ - 'appName': app.name, - 'languageCode': languageCode, - })))!; - - this.languageCode = data['languageCode']; - } catch (e, stack) { - convertPlatformException(e, stack); - } - } - - @override - Future setSettings({ - bool? appVerificationDisabledForTesting, - String? userAccessGroup, - String? phoneNumber, - String? smsCode, - bool? forceRecaptchaFlow, - }) async { - if (phoneNumber != null && smsCode == null || - phoneNumber == null && smsCode != null) { - throw ArgumentError( - "The [smsCode] and the [phoneNumber] must both be either 'null' or a 'String''.", + final result = await _api.signInWithCredential( + pigeonDefault, + credential.asMap(), ); - } - // argument for every platform - var arguments = { - 'appVerificationDisabledForTesting': appVerificationDisabledForTesting, - }; - - if (Platform.isIOS || Platform.isMacOS) { - arguments['userAccessGroup'] = userAccessGroup; - } - - if (Platform.isAndroid) { - if (phoneNumber != null && smsCode != null) { - arguments['phoneNumber'] = phoneNumber; - arguments['smsCode'] = smsCode; - } - - if (forceRecaptchaFlow != null) { - arguments['forceRecaptchaFlow'] = forceRecaptchaFlow; - } - } - - try { - await channel.invokeMethod( - 'Auth#setSettings', _withChannelDefaults(arguments)); - } catch (e, stack) { - convertPlatformException(e, stack); - } - } - - @override - Future setPersistence(Persistence persistence) { - throw UnimplementedError( - 'setPersistence() is only supported on web based platforms'); - } - - @override - Future signInAnonymously() async { - try { - Map data = - (await channel.invokeMapMethod( - 'Auth#signInAnonymously', _withChannelDefaults({})))!; MethodChannelUserCredential userCredential = - MethodChannelUserCredential(this, data); + MethodChannelUserCredential(this, result); currentUser = userCredential.user; return userCredential; @@ -451,19 +309,15 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { } @override - Future signInWithCredential( - AuthCredential credential, - ) async { + Future signInWithCustomToken(String token) async { try { - Map data = - (await channel.invokeMapMethod( - 'Auth#signInWithCredential', - _withChannelDefaults({ - 'credential': credential.asMap(), - })))!; + final result = await _api.signInWithCustomToken( + pigeonDefault, + token, + ); MethodChannelUserCredential userCredential = - MethodChannelUserCredential(this, data); + MethodChannelUserCredential(this, result); currentUser = userCredential.user; return userCredential; @@ -473,17 +327,17 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { } @override - Future signInWithCustomToken(String token) async { + Future signInWithEmailAndPassword( + String email, String password) async { try { - Map data = - (await channel.invokeMapMethod( - 'Auth#signInWithCustomToken', - _withChannelDefaults({ - 'token': token, - })))!; + final result = await _api.signInWithEmailAndPassword( + pigeonDefault, + email, + password, + ); MethodChannelUserCredential userCredential = - MethodChannelUserCredential(this, data); + MethodChannelUserCredential(this, result); currentUser = userCredential.user; return userCredential; @@ -493,19 +347,17 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { } @override - Future signInWithEmailAndPassword( - String email, String password) async { + Future signInWithEmailLink( + String email, String emailLink) async { try { - Map data = - (await channel.invokeMapMethod( - 'Auth#signInWithEmailAndPassword', - _withChannelDefaults({ - 'email': email, - 'password': password, - })))!; + final result = await _api.signInWithEmailLink( + pigeonDefault, + email, + emailLink, + ); MethodChannelUserCredential userCredential = - MethodChannelUserCredential(this, data); + MethodChannelUserCredential(this, result); currentUser = userCredential.user; return userCredential; @@ -515,19 +367,28 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { } @override - Future signInWithEmailLink( - String email, String emailLink) async { + Future signInWithProvider( + AuthProvider provider, + ) async { try { - Map data = - (await channel.invokeMapMethod( - 'Auth#signInWithEmailLink', - _withChannelDefaults({ - 'email': email, - 'emailLink': emailLink, - })))!; + // To extract scopes and custom parameters from the provider + final convertedProvider = convertToOAuthProvider(provider); + + final result = await _api.signInWithProvider( + pigeonDefault, + PigeonSignInProvider( + providerId: convertedProvider.providerId, + scopes: convertedProvider is OAuthProvider + ? convertedProvider.scopes + : null, + customParameters: convertedProvider is OAuthProvider + ? convertedProvider.parameters + : null, + ), + ); MethodChannelUserCredential userCredential = - MethodChannelUserCredential(this, data); + MethodChannelUserCredential(this, result); currentUser = userCredential.user; return userCredential; @@ -553,8 +414,7 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { @override Future signOut() async { try { - await channel.invokeMethod( - 'Auth#signOut', _withChannelDefaults({})); + await _api.signOut(pigeonDefault); currentUser = null; } catch (e, stack) { @@ -563,45 +423,144 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { } @override - Future verifyPasswordResetCode(String code) async { + Future> fetchSignInMethodsForEmail(String email) async { try { - Map data = - (await channel.invokeMapMethod( - 'Auth#verifyPasswordResetCode', - _withChannelDefaults({ - 'code': code, - })))!; - - return data['email']; + final data = await _api.fetchSignInMethodsForEmail(pigeonDefault, email); + + return data.whereNotNull().toList(); } catch (e, stack) { convertPlatformException(e, stack); } } @override - Future signInWithProvider( - AuthProvider provider, + Stream authStateChanges() async* { + yield currentUser; + yield* _authStateChangesListeners[app.name]! + .stream + .map((event) => event.value); + } + + @override + Stream idTokenChanges() async* { + yield currentUser; + yield* _idTokenChangesListeners[app.name]! + .stream + .map((event) => event.value); + } + + @override + Stream userChanges() async* { + yield currentUser; + yield* _userChangesListeners[app.name]!.stream.map((event) => event.value); + } + + @override + Future sendPasswordResetEmail( + String email, [ + ActionCodeSettings? actionCodeSettings, + ]) async { + try { + await _api.sendPasswordResetEmail( + pigeonDefault, + email, + actionCodeSettings == null + ? null + : PigeonActionCodeSettings( + url: actionCodeSettings.url, + handleCodeInApp: actionCodeSettings.handleCodeInApp, + iOSBundleId: actionCodeSettings.iOSBundleId, + androidPackageName: actionCodeSettings.androidPackageName, + androidInstallApp: actionCodeSettings.androidInstallApp, + androidMinimumVersion: actionCodeSettings.androidMinimumVersion, + dynamicLinkDomain: actionCodeSettings.dynamicLinkDomain, + ), + ); + } catch (e, stack) { + convertPlatformException(e, stack); + } + } + + @override + Future sendSignInLinkToEmail( + String email, + ActionCodeSettings actionCodeSettings, ) async { try { - // To extract scopes and custom parameters from the provider - final convertedProvider = convertToOAuthProvider(provider); + await _api.sendSignInLinkToEmail( + pigeonDefault, + email, + PigeonActionCodeSettings( + url: actionCodeSettings.url, + handleCodeInApp: actionCodeSettings.handleCodeInApp, + iOSBundleId: actionCodeSettings.iOSBundleId, + androidPackageName: actionCodeSettings.androidPackageName, + androidInstallApp: actionCodeSettings.androidInstallApp, + androidMinimumVersion: actionCodeSettings.androidMinimumVersion, + dynamicLinkDomain: actionCodeSettings.dynamicLinkDomain, + ), + ); + } catch (e, stack) { + convertPlatformException(e, stack); + } + } - Map data = - (await channel.invokeMapMethod( - 'Auth#signInWithProvider', - _withChannelDefaults({ - 'signInProvider': convertedProvider.providerId, - if (convertedProvider is OAuthProvider) ...{ - 'scopes': convertedProvider.scopes, - 'customParameters': convertedProvider.parameters - }, - })))!; + @override + Future setLanguageCode(String? languageCode) async { + try { + final newLanguageCode = + await _api.setLanguageCode(pigeonDefault, languageCode); - MethodChannelUserCredential userCredential = - MethodChannelUserCredential(this, data); + this.languageCode = newLanguageCode; + } catch (e, stack) { + convertPlatformException(e, stack); + } + } - currentUser = userCredential.user; - return userCredential; + @override + Future setSettings({ + bool appVerificationDisabledForTesting = false, + String? userAccessGroup, + String? phoneNumber, + String? smsCode, + bool? forceRecaptchaFlow, + }) async { + if (phoneNumber != null && smsCode == null || + phoneNumber == null && smsCode != null) { + throw ArgumentError( + "The [smsCode] and the [phoneNumber] must both be either 'null' or a 'String''.", + ); + } + + try { + await _api.setSettings( + pigeonDefault, + PigeonFirebaseAuthSettings( + appVerificationDisabledForTesting: + appVerificationDisabledForTesting, + userAccessGroup: userAccessGroup, + phoneNumber: phoneNumber, + smsCode: smsCode, + forceRecaptchaFlow: forceRecaptchaFlow, + )); + } catch (e, stack) { + convertPlatformException(e, stack); + } + } + + @override + Future setPersistence(Persistence persistence) { + throw UnimplementedError( + 'setPersistence() is only supported on web based platforms', + ); + } + + @override + Future verifyPasswordResetCode(String code) async { + try { + final userEmail = await _api.verifyPasswordResetCode(pigeonDefault, code); + + return userEmail; } catch (e, stack) { convertPlatformException(e, stack); } @@ -627,20 +586,19 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { } try { - final eventChannelName = await channel.invokeMethod( - 'Auth#verifyPhoneNumber', - _withChannelDefaults({ - if (phoneNumber != null) 'phoneNumber': phoneNumber, - if (multiFactorInfo?.uid != null) - 'multiFactorInfo': multiFactorInfo?.uid, - 'timeout': timeout.inMilliseconds, - 'forceResendingToken': forceResendingToken, - 'autoRetrievedSmsCodeForTesting': autoRetrievedSmsCodeForTesting, - if (multiFactorSession?.id != null) - 'multiFactorSessionId': multiFactorSession!.id, - })); - - EventChannel(eventChannelName!) + final eventChannelName = await _api.verifyPhoneNumber( + pigeonDefault, + PigeonVerifyPhoneNumberRequest( + phoneNumber: phoneNumber, + multiFactorInfoId: multiFactorInfo?.uid, + timeout: timeout.inMilliseconds, + forceResendingToken: forceResendingToken, + autoRetrievedSmsCodeForTesting: autoRetrievedSmsCodeForTesting, + multiFactorSessionId: multiFactorSession?.id, + ), + ); + + EventChannel(eventChannelName) .receiveGuardedBroadcastStream(onError: convertPlatformException) .listen((arguments) { final name = arguments['name']; @@ -656,8 +614,8 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { final Map? details = error?['details']; FirebaseAuthException exception = FirebaseAuthException( - message: details != null ? details['message'] : error?['message'], - code: details?['code'] ?? 'unknown', + message: details?['message'] ?? error?['message'], + code: details?['code'] ?? error?['code'] ?? 'unknown', ); verificationFailed(exception); diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_multi_factor.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_multi_factor.dart index fa60b16a194d..ecb26c7420d8 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_multi_factor.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_multi_factor.dart @@ -15,13 +15,20 @@ class MethodChannelMultiFactor extends MultiFactorPlatform { final _api = MultiFactorUserHostApi(); + PigeonFirebaseApp get pigeonDefault { + return PigeonFirebaseApp( + appName: auth.app.name, + tenantId: auth.tenantId, + ); + } + @override Future getSession() async { try { - final pigeonObject = await _api.getSession(auth.app.name); + final pigeonObject = await _api.getSession(pigeonDefault); return MultiFactorSession(pigeonObject.id); } catch (e, stack) { - convertPlatformException(e, stack, fromPigeon: true); + convertPlatformException(e, stack); } } @@ -46,7 +53,7 @@ class MethodChannelMultiFactor extends MultiFactorPlatform { try { await _api.enrollPhone( - auth.app.name, + pigeonDefault, PigeonPhoneMultiFactorAssertion( verificationId: verificationId, verificationCode: verificationCode, @@ -54,7 +61,7 @@ class MethodChannelMultiFactor extends MultiFactorPlatform { displayName, ); } catch (e, stack) { - convertPlatformException(e, stack, fromPigeon: true); + convertPlatformException(e, stack); } } else { throw UnimplementedError( @@ -77,21 +84,21 @@ class MethodChannelMultiFactor extends MultiFactorPlatform { try { await _api.unenroll( - auth.app.name, + pigeonDefault, uidToUnenroll, ); } catch (e, stack) { - convertPlatformException(e, stack, fromPigeon: true); + convertPlatformException(e, stack); } } @override Future> getEnrolledFactors() async { try { - final data = await _api.getEnrolledFactors(auth.app.name); + final data = await _api.getEnrolledFactors(pigeonDefault); return multiFactorInfoPigeonToObject(data); } catch (e, stack) { - convertPlatformException(e, stack, fromPigeon: true); + convertPlatformException(e, stack); } } } @@ -130,7 +137,7 @@ class MethodChannelMultiFactorResolver extends MultiFactorResolverPlatform { } try { - final data = await _api.resolveSignIn( + final result = await _api.resolveSignIn( _resolverId, PigeonPhoneMultiFactorAssertion( verificationId: verificationId, @@ -139,11 +146,11 @@ class MethodChannelMultiFactorResolver extends MultiFactorResolverPlatform { ); MethodChannelUserCredential userCredential = - MethodChannelUserCredential(_auth, data.cast()); + MethodChannelUserCredential(_auth, result); return userCredential; } catch (e, stack) { - convertPlatformException(e, stack, fromPigeon: true); + convertPlatformException(e, stack); } } else { throw UnimplementedError( diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user.dart index adf7d78caea0..e6d3d3f0d8e9 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user.dart @@ -6,9 +6,9 @@ import 'dart:async'; import 'package:firebase_auth_platform_interface/firebase_auth_platform_interface.dart'; -import 'package:firebase_auth_platform_interface/src/method_channel/method_channel_firebase_auth.dart'; import 'package:firebase_auth_platform_interface/src/method_channel/method_channel_user_credential.dart'; import 'package:firebase_auth_platform_interface/src/method_channel/utils/convert_auth_provider.dart'; +import 'package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart'; import 'utils/exception.dart'; @@ -16,43 +16,36 @@ import 'utils/exception.dart'; class MethodChannelUser extends UserPlatform { /// Constructs a new [MethodChannelUser] instance. MethodChannelUser(FirebaseAuthPlatform auth, MultiFactorPlatform multiFactor, - Map data) + PigeonUserDetails data) : super(auth, multiFactor, data); - /// Attaches generic default values to method channel arguments. - Map _withChannelDefaults(Map other) { - return { - 'appName': auth.app.name, - 'tenantId': auth.tenantId, - }..addAll(other); + final _api = FirebaseAuthUserHostApi(); + + PigeonFirebaseApp get pigeonDefault { + return PigeonFirebaseApp( + appName: auth.app.name, + tenantId: auth.tenantId, + ); } @override Future delete() async { try { - await MethodChannelFirebaseAuth.channel.invokeMethod( - 'User#delete', - _withChannelDefaults({}), - ); + await _api.delete(pigeonDefault); } catch (e, stack) { convertPlatformException(e, stack); } } @override - Future getIdToken(bool forceRefresh) async { + Future getIdToken(bool forceRefresh) async { try { - Map data = (await MethodChannelFirebaseAuth.channel - .invokeMapMethod( - 'User#getIdToken', - _withChannelDefaults( - { - 'forceRefresh': forceRefresh, - 'tokenOnly': true, - }, - )))!; - - return data['token']; + final data = await _api.getIdToken( + pigeonDefault, + forceRefresh, + ); + + return data.token; } catch (e, stack) { convertPlatformException(e, stack); } @@ -61,14 +54,10 @@ class MethodChannelUser extends UserPlatform { @override Future getIdTokenResult(bool forceRefresh) async { try { - Map data = (await MethodChannelFirebaseAuth.channel - .invokeMapMethod( - 'User#getIdToken', - _withChannelDefaults({ - 'forceRefresh': forceRefresh, - 'tokenOnly': false, - }), - ))!; + final data = await _api.getIdToken( + pigeonDefault, + forceRefresh, + ); return IdTokenResult(data); } catch (e, stack) { @@ -81,17 +70,13 @@ class MethodChannelUser extends UserPlatform { AuthCredential credential, ) async { try { - Map data = (await MethodChannelFirebaseAuth.channel - .invokeMapMethod( - 'User#linkWithCredential', - _withChannelDefaults( - { - 'credential': credential.asMap(), - }, - )))!; + final result = await _api.linkWithCredential( + pigeonDefault, + credential.asMap(), + ); MethodChannelUserCredential userCredential = - MethodChannelUserCredential(auth, data); + MethodChannelUserCredential(auth, result); auth.currentUser = userCredential.user; return userCredential; @@ -108,19 +93,21 @@ class MethodChannelUser extends UserPlatform { // To extract scopes and custom parameters from the provider final convertedProvider = convertToOAuthProvider(provider); - Map data = (await MethodChannelFirebaseAuth.channel - .invokeMapMethod( - 'User#linkWithProvider', - _withChannelDefaults({ - 'signInProvider': convertedProvider.providerId, - if (convertedProvider is OAuthProvider) ...{ - 'scopes': convertedProvider.scopes, - 'customParameters': convertedProvider.parameters - }, - })))!; + final result = await _api.linkWithProvider( + pigeonDefault, + PigeonSignInProvider( + providerId: convertedProvider.providerId, + scopes: convertedProvider is OAuthProvider + ? convertedProvider.scopes + : null, + customParameters: convertedProvider is OAuthProvider + ? convertedProvider.parameters + : null, + ), + ); MethodChannelUserCredential userCredential = - MethodChannelUserCredential(auth, data); + MethodChannelUserCredential(auth, result); auth.currentUser = userCredential.user; return userCredential; @@ -130,26 +117,17 @@ class MethodChannelUser extends UserPlatform { } @override - Future reauthenticateWithProvider( - AuthProvider provider, + Future reauthenticateWithCredential( + AuthCredential credential, ) async { try { - // To extract scopes and custom parameters from the provider - final convertedProvider = convertToOAuthProvider(provider); - - Map data = (await MethodChannelFirebaseAuth.channel - .invokeMapMethod( - 'User#reauthenticateWithProvider', - _withChannelDefaults({ - 'signInProvider': convertedProvider.providerId, - if (convertedProvider is OAuthProvider) ...{ - 'scopes': convertedProvider.scopes, - 'customParameters': convertedProvider.parameters - }, - })))!; + final result = await _api.reauthenticateWithCredential( + pigeonDefault, + credential.asMap(), + ); MethodChannelUserCredential userCredential = - MethodChannelUserCredential(auth, data); + MethodChannelUserCredential(auth, result); auth.currentUser = userCredential.user; return userCredential; @@ -159,21 +137,28 @@ class MethodChannelUser extends UserPlatform { } @override - Future reauthenticateWithCredential( - AuthCredential credential, + Future reauthenticateWithProvider( + AuthProvider provider, ) async { try { - Map data = (await MethodChannelFirebaseAuth.channel - .invokeMapMethod( - 'User#reauthenticateUserWithCredential', - _withChannelDefaults( - { - 'credential': credential.asMap(), - }, - )))!; + // To extract scopes and custom parameters from the provider + final convertedProvider = convertToOAuthProvider(provider); + + final result = await _api.reauthenticateWithProvider( + pigeonDefault, + PigeonSignInProvider( + providerId: convertedProvider.providerId, + scopes: convertedProvider is OAuthProvider + ? convertedProvider.scopes + : null, + customParameters: convertedProvider is OAuthProvider + ? convertedProvider.parameters + : null, + ), + ); MethodChannelUserCredential userCredential = - MethodChannelUserCredential(auth, data); + MethodChannelUserCredential(auth, result); auth.currentUser = userCredential.user; return userCredential; @@ -185,11 +170,10 @@ class MethodChannelUser extends UserPlatform { @override Future reload() async { try { - Map data = (await MethodChannelFirebaseAuth.channel - .invokeMapMethod( - 'User#reload', _withChannelDefaults({})))!; + final result = await _api.reload(pigeonDefault); - MethodChannelUser user = MethodChannelUser(auth, super.multiFactor, data); + MethodChannelUser user = + MethodChannelUser(auth, super.multiFactor, result); auth.currentUser = user; auth.sendAuthChangesEvent(auth.app.name, user); } catch (e, stack) { @@ -202,10 +186,20 @@ class MethodChannelUser extends UserPlatform { ActionCodeSettings? actionCodeSettings, ) async { try { - await MethodChannelFirebaseAuth.channel.invokeMethod( - 'User#sendEmailVerification', - _withChannelDefaults( - {'actionCodeSettings': actionCodeSettings?.asMap()})); + await _api.sendEmailVerification( + pigeonDefault, + actionCodeSettings == null + ? null + : PigeonActionCodeSettings( + url: actionCodeSettings.url, + handleCodeInApp: actionCodeSettings.handleCodeInApp, + iOSBundleId: actionCodeSettings.iOSBundleId, + androidPackageName: actionCodeSettings.androidPackageName, + androidInstallApp: actionCodeSettings.androidInstallApp, + androidMinimumVersion: actionCodeSettings.androidMinimumVersion, + dynamicLinkDomain: actionCodeSettings.dynamicLinkDomain, + ), + ); } catch (e, stack) { convertPlatformException(e, stack); } @@ -214,18 +208,11 @@ class MethodChannelUser extends UserPlatform { @override Future unlink(String providerId) async { try { - Map data = (await MethodChannelFirebaseAuth.channel - .invokeMapMethod( - 'User#unlink', - _withChannelDefaults( - { - 'providerId': providerId, - }, - )))!; + final result = await _api.unlink(pigeonDefault, providerId); // Native returns a UserCredential, whereas Dart should expect a User MethodChannelUserCredential userCredential = - MethodChannelUserCredential(auth, data); + MethodChannelUserCredential(auth, result); MethodChannelUser? user = userCredential.user as MethodChannelUser?; auth.currentUser = user; @@ -239,16 +226,10 @@ class MethodChannelUser extends UserPlatform { @override Future updateEmail(String newEmail) async { try { - Map data = (await MethodChannelFirebaseAuth.channel - .invokeMapMethod( - 'User#updateEmail', - _withChannelDefaults( - { - 'newEmail': newEmail, - }, - )))!; - - MethodChannelUser user = MethodChannelUser(auth, super.multiFactor, data); + final result = await _api.updateEmail(pigeonDefault, newEmail); + + MethodChannelUser user = + MethodChannelUser(auth, super.multiFactor, result); auth.currentUser = user; auth.sendAuthChangesEvent(auth.app.name, user); } catch (e, stack) { @@ -259,16 +240,10 @@ class MethodChannelUser extends UserPlatform { @override Future updatePassword(String newPassword) async { try { - Map data = (await MethodChannelFirebaseAuth.channel - .invokeMapMethod( - 'User#updatePassword', - _withChannelDefaults( - { - 'newPassword': newPassword, - }, - )))!; - - MethodChannelUser user = MethodChannelUser(auth, super.multiFactor, data); + final result = await _api.updatePassword(pigeonDefault, newPassword); + + MethodChannelUser user = + MethodChannelUser(auth, super.multiFactor, result); auth.currentUser = user; auth.sendAuthChangesEvent(auth.app.name, user); } catch (e, stack) { @@ -279,16 +254,13 @@ class MethodChannelUser extends UserPlatform { @override Future updatePhoneNumber(PhoneAuthCredential phoneCredential) async { try { - Map data = (await MethodChannelFirebaseAuth.channel - .invokeMapMethod( - 'User#updatePhoneNumber', - _withChannelDefaults( - { - 'credential': phoneCredential.asMap(), - }, - )))!; - - MethodChannelUser user = MethodChannelUser(auth, super.multiFactor, data); + final result = await _api.updatePhoneNumber( + pigeonDefault, + phoneCredential.asMap(), + ); + + MethodChannelUser user = + MethodChannelUser(auth, super.multiFactor, result); auth.currentUser = user; auth.sendAuthChangesEvent(auth.app.name, user); } catch (e, stack) { @@ -299,16 +271,17 @@ class MethodChannelUser extends UserPlatform { @override Future updateProfile(Map profile) async { try { - Map data = (await MethodChannelFirebaseAuth.channel - .invokeMapMethod( - 'User#updateProfile', - _withChannelDefaults( - { - 'profile': profile, - }, - )))!; - - MethodChannelUser user = MethodChannelUser(auth, super.multiFactor, data); + final result = await _api.updateProfile( + pigeonDefault, + PigeonUserProfile( + displayName: profile['displayName'], + photoUrl: profile['photoURL'], + displayNameChanged: profile.containsKey('displayName'), + photoUrlChanged: profile.containsKey('photoURL'), + ), + ); + MethodChannelUser user = + MethodChannelUser(auth, super.multiFactor, result); auth.currentUser = user; auth.sendAuthChangesEvent(auth.app.name, user); } catch (e, stack) { @@ -322,14 +295,21 @@ class MethodChannelUser extends UserPlatform { ActionCodeSettings? actionCodeSettings, ]) async { try { - await MethodChannelFirebaseAuth.channel.invokeMethod( - 'User#verifyBeforeUpdateEmail', - _withChannelDefaults( - { - 'newEmail': newEmail, - 'actionCodeSettings': actionCodeSettings?.asMap(), - }, - )); + await _api.verifyBeforeUpdateEmail( + pigeonDefault, + newEmail, + actionCodeSettings == null + ? null + : PigeonActionCodeSettings( + url: actionCodeSettings.url, + handleCodeInApp: actionCodeSettings.handleCodeInApp, + iOSBundleId: actionCodeSettings.iOSBundleId, + androidPackageName: actionCodeSettings.androidPackageName, + androidInstallApp: actionCodeSettings.androidInstallApp, + androidMinimumVersion: actionCodeSettings.androidMinimumVersion, + dynamicLinkDomain: actionCodeSettings.dynamicLinkDomain, + ), + ); } catch (e, stack) { convertPlatformException(e, stack); } diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user_credential.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user_credential.dart index 1b3ceb77d447..c33cbbc3ab2d 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user_credential.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user_credential.dart @@ -6,34 +6,38 @@ import 'package:firebase_auth_platform_interface/firebase_auth_platform_interface.dart'; import 'package:firebase_auth_platform_interface/src/method_channel/method_channel_multi_factor.dart'; import 'package:firebase_auth_platform_interface/src/method_channel/method_channel_user.dart'; +import 'package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart'; /// Method Channel delegate for [UserCredentialPlatform]. class MethodChannelUserCredential extends UserCredentialPlatform { // ignore: public_member_api_docs MethodChannelUserCredential( - FirebaseAuthPlatform auth, Map data) + FirebaseAuthPlatform auth, PigeonUserCredential data) : super( auth: auth, - additionalUserInfo: data['additionalUserInfo'] == null + additionalUserInfo: data.additionalUserInfo == null ? null : AdditionalUserInfo( - isNewUser: data['additionalUserInfo']['isNewUser'], + isNewUser: data.additionalUserInfo!.isNewUser, profile: Map.from( - data['additionalUserInfo']['profile'] ?? {}), - providerId: data['additionalUserInfo']['providerId'], - username: data['additionalUserInfo']['username'], + data.additionalUserInfo!.profile ?? {}), + providerId: data.additionalUserInfo!.providerId, + username: data.additionalUserInfo!.username, ), - credential: data['authCredential'] == null + credential: data.credential == null ? null : AuthCredential( - providerId: data['authCredential']['providerId'], - signInMethod: data['authCredential']['signInMethod'], - token: data['authCredential']['token'], - accessToken: data['authCredential']['accessToken'], + providerId: data.credential!.providerId, + signInMethod: data.credential!.signInMethod, + token: data.credential!.nativeId, + accessToken: data.credential!.accessToken, ), - user: data['user'] == null + user: data.user == null ? null - : MethodChannelUser(auth, MethodChannelMultiFactor(auth), - Map.from(data['user'])), + : MethodChannelUser( + auth, + MethodChannelMultiFactor(auth), + data.user!, + ), ); } diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/exception.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/exception.dart index a7b4ce774fb9..c51c6b173055 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/exception.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/exception.dart @@ -17,7 +17,7 @@ import 'package:flutter/services.dart'; Never convertPlatformException( Object exception, StackTrace stackTrace, { - bool fromPigeon = false, + bool fromPigeon = true, }) { if (exception is! PlatformException) { Error.throwWithStackTrace(exception, stackTrace); @@ -34,19 +34,38 @@ Never convertPlatformException( /// A [PlatformException] can only be converted to a [FirebaseAuthException] if /// the `details` of the exception exist. Firebase returns specific codes and /// messages which can be converted into user friendly exceptions. -// TODO(rousselGit): Should this return a FirebaseAuthException to avoid having to cast? FirebaseException platformExceptionToFirebaseAuthException( PlatformException platformException, { - bool fromPigeon = false, + bool fromPigeon = true, }) { if (fromPigeon) { + var code = platformException.code + .replaceAll('ERROR_', '') + .toLowerCase() + .replaceAll('_', '-'); + + final customCode = _getCustomCode( + platformException.details, + platformException.message, + ); + if (customCode != null) { + code = customCode; + } + + if (code.isNotEmpty) { + if (code == kMultiFactorError) { + return parseMultiFactorError(platformException); + } + } + return FirebaseAuthException( - code: platformException.code, - // Remove leading classname from message + code: code, message: platformException.message?.split(': ').last, ); } + // Parsing code to match the format of the other platforms + Map? details = platformException.details != null ? Map.from(platformException.details) : null; @@ -59,7 +78,7 @@ FirebaseException platformExceptionToFirebaseAuthException( if (details != null) { code = details['code'] ?? code; if (code == 'second-factor-required') { - return parseMultiFactorError(details); + return parseMultiFactorError(platformException); } message = details['message'] ?? message; @@ -113,11 +132,13 @@ String? _getCustomCode(Map? additionalData, String? message) { return null; } +const kMultiFactorError = 'second-factor-required'; + FirebaseAuthMultiFactorExceptionPlatform parseMultiFactorError( - Map details) { - final code = details['code'] as String?; - final message = details['message'] as String?; - final additionalData = details['additionalData'] as Map?; + PlatformException exception) { + const code = kMultiFactorError; + final message = exception.message; + final additionalData = exception.details as Map?; if (additionalData == null) { throw FirebaseAuthException( @@ -143,7 +164,7 @@ FirebaseAuthMultiFactorExceptionPlatform parseMultiFactorError( if (auth == null) { throw FirebaseAuthException( - code: code ?? 'Unknown', + code: code, message: message, ); } @@ -164,7 +185,7 @@ FirebaseAuthMultiFactorExceptionPlatform parseMultiFactorError( ); return FirebaseAuthMultiFactorExceptionPlatform( - code: code ?? 'Unknown', + code: code, message: message, resolver: multiFactorResolver, ); diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/pigeon/messages.pigeon.dart index a3a29aebbd81..36fb0e7a3a83 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -1,96 +1,1843 @@ -// Copyright 2022, the Chromium project authors. Please see the AUTHORS file +// Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v3.2.3), do not edit directly. +// Autogenerated from Pigeon (v9.2.4), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import + import 'dart:async'; -import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +/// The type of operation that generated the action code from calling +/// [checkActionCode]. +enum ActionCodeInfoOperation { + /// Unknown operation. + unknown, + + /// Password reset code generated via [sendPasswordResetEmail]. + passwordReset, + + /// Email verification code generated via [User.sendEmailVerification]. + verifyEmail, + + /// Email change revocation code generated via [User.updateEmail]. + recoverEmail, + + /// Email sign in code generated via [sendSignInLinkToEmail]. + emailSignIn, + + /// Verify and change email code generated via [User.verifyBeforeUpdateEmail]. + verifyAndChangeEmail, + + /// Action code for reverting second factor addition. + revertSecondFactorAddition, +} + +class PigeonMultiFactorSession { + PigeonMultiFactorSession({ + required this.id, + }); + + String id; + + Object encode() { + return [ + id, + ]; + } + + static PigeonMultiFactorSession decode(Object result) { + result as List; + return PigeonMultiFactorSession( + id: result[0]! as String, + ); + } +} + +class PigeonPhoneMultiFactorAssertion { + PigeonPhoneMultiFactorAssertion({ + required this.verificationId, + required this.verificationCode, + }); + + String verificationId; + + String verificationCode; + + Object encode() { + return [ + verificationId, + verificationCode, + ]; + } + + static PigeonPhoneMultiFactorAssertion decode(Object result) { + result as List; + return PigeonPhoneMultiFactorAssertion( + verificationId: result[0]! as String, + verificationCode: result[1]! as String, + ); + } +} + +class PigeonMultiFactorInfo { + PigeonMultiFactorInfo({ + this.displayName, + required this.enrollmentTimestamp, + this.factorId, + required this.uid, + this.phoneNumber, + }); + + String? displayName; + + double enrollmentTimestamp; + + String? factorId; + + String uid; + + String? phoneNumber; + + Object encode() { + return [ + displayName, + enrollmentTimestamp, + factorId, + uid, + phoneNumber, + ]; + } + + static PigeonMultiFactorInfo decode(Object result) { + result as List; + return PigeonMultiFactorInfo( + displayName: result[0] as String?, + enrollmentTimestamp: result[1]! as double, + factorId: result[2] as String?, + uid: result[3]! as String, + phoneNumber: result[4] as String?, + ); + } +} + +class PigeonFirebaseApp { + PigeonFirebaseApp({ + required this.appName, + this.tenantId, + }); + + String appName; + + String? tenantId; + + Object encode() { + return [ + appName, + tenantId, + ]; + } + + static PigeonFirebaseApp decode(Object result) { + result as List; + return PigeonFirebaseApp( + appName: result[0]! as String, + tenantId: result[1] as String?, + ); + } +} + +class PigeonActionCodeInfo { + PigeonActionCodeInfo({ + required this.operation, + required this.data, + }); + + ActionCodeInfoOperation operation; + + PigeonActionCodeInfoData data; + + Object encode() { + return [ + operation.index, + data.encode(), + ]; + } + + static PigeonActionCodeInfo decode(Object result) { + result as List; + return PigeonActionCodeInfo( + operation: ActionCodeInfoOperation.values[result[0]! as int], + data: PigeonActionCodeInfoData.decode(result[1]! as List), + ); + } +} + +class PigeonActionCodeInfoData { + PigeonActionCodeInfoData({ + this.email, + this.previousEmail, + }); + + String? email; + + String? previousEmail; + + Object encode() { + return [ + email, + previousEmail, + ]; + } + + static PigeonActionCodeInfoData decode(Object result) { + result as List; + return PigeonActionCodeInfoData( + email: result[0] as String?, + previousEmail: result[1] as String?, + ); + } +} + +class PigeonUserCredential { + PigeonUserCredential({ + this.user, + this.additionalUserInfo, + this.credential, + }); + + PigeonUserDetails? user; + + PigeonAdditionalUserInfo? additionalUserInfo; + + PigeonAuthCredential? credential; + + Object encode() { + return [ + user?.encode(), + additionalUserInfo?.encode(), + credential?.encode(), + ]; + } + + static PigeonUserCredential decode(Object result) { + result as List; + return PigeonUserCredential( + user: result[0] != null + ? PigeonUserDetails.decode(result[0]! as List) + : null, + additionalUserInfo: result[1] != null + ? PigeonAdditionalUserInfo.decode(result[1]! as List) + : null, + credential: result[2] != null + ? PigeonAuthCredential.decode(result[2]! as List) + : null, + ); + } +} + +class PigeonAdditionalUserInfo { + PigeonAdditionalUserInfo({ + required this.isNewUser, + this.providerId, + this.username, + this.profile, + }); + + bool isNewUser; + + String? providerId; + + String? username; + + Map? profile; + + Object encode() { + return [ + isNewUser, + providerId, + username, + profile, + ]; + } + + static PigeonAdditionalUserInfo decode(Object result) { + result as List; + return PigeonAdditionalUserInfo( + isNewUser: result[0]! as bool, + providerId: result[1] as String?, + username: result[2] as String?, + profile: (result[3] as Map?)?.cast(), + ); + } +} + +class PigeonAuthCredential { + PigeonAuthCredential({ + required this.providerId, + required this.signInMethod, + required this.nativeId, + this.accessToken, + }); + + String providerId; + + String signInMethod; + + int nativeId; + + String? accessToken; + + Object encode() { + return [ + providerId, + signInMethod, + nativeId, + accessToken, + ]; + } + + static PigeonAuthCredential decode(Object result) { + result as List; + return PigeonAuthCredential( + providerId: result[0]! as String, + signInMethod: result[1]! as String, + nativeId: result[2]! as int, + accessToken: result[3] as String?, + ); + } +} + +class PigeonUserInfo { + PigeonUserInfo({ + required this.uid, + this.email, + this.displayName, + this.photoUrl, + this.phoneNumber, + required this.isAnonymous, + required this.isEmailVerified, + this.providerId, + this.tenantId, + this.refreshToken, + this.creationTimestamp, + this.lastSignInTimestamp, + }); + + String uid; + + String? email; + + String? displayName; + + String? photoUrl; + + String? phoneNumber; + + bool isAnonymous; + + bool isEmailVerified; + + String? providerId; + + String? tenantId; + + String? refreshToken; + + int? creationTimestamp; + + int? lastSignInTimestamp; + + Object encode() { + return [ + uid, + email, + displayName, + photoUrl, + phoneNumber, + isAnonymous, + isEmailVerified, + providerId, + tenantId, + refreshToken, + creationTimestamp, + lastSignInTimestamp, + ]; + } + + static PigeonUserInfo decode(Object result) { + result as List; + return PigeonUserInfo( + uid: result[0]! as String, + email: result[1] as String?, + displayName: result[2] as String?, + photoUrl: result[3] as String?, + phoneNumber: result[4] as String?, + isAnonymous: result[5]! as bool, + isEmailVerified: result[6]! as bool, + providerId: result[7] as String?, + tenantId: result[8] as String?, + refreshToken: result[9] as String?, + creationTimestamp: result[10] as int?, + lastSignInTimestamp: result[11] as int?, + ); + } +} + +class PigeonUserDetails { + PigeonUserDetails({ + required this.userInfo, + required this.providerData, + }); + + PigeonUserInfo userInfo; + + List?> providerData; + + Object encode() { + return [ + userInfo.encode(), + providerData, + ]; + } + + static PigeonUserDetails decode(Object result) { + result as List; + return PigeonUserDetails( + userInfo: PigeonUserInfo.decode(result[0]! as List), + providerData: + (result[1] as List?)!.cast?>(), + ); + } +} + +class PigeonActionCodeSettings { + PigeonActionCodeSettings({ + required this.url, + this.dynamicLinkDomain, + required this.handleCodeInApp, + this.iOSBundleId, + this.androidPackageName, + required this.androidInstallApp, + this.androidMinimumVersion, + }); + + String url; + + String? dynamicLinkDomain; + + bool handleCodeInApp; + + String? iOSBundleId; + + String? androidPackageName; + + bool androidInstallApp; + + String? androidMinimumVersion; + + Object encode() { + return [ + url, + dynamicLinkDomain, + handleCodeInApp, + iOSBundleId, + androidPackageName, + androidInstallApp, + androidMinimumVersion, + ]; + } + + static PigeonActionCodeSettings decode(Object result) { + result as List; + return PigeonActionCodeSettings( + url: result[0]! as String, + dynamicLinkDomain: result[1] as String?, + handleCodeInApp: result[2]! as bool, + iOSBundleId: result[3] as String?, + androidPackageName: result[4] as String?, + androidInstallApp: result[5]! as bool, + androidMinimumVersion: result[6] as String?, + ); + } +} + +class PigeonFirebaseAuthSettings { + PigeonFirebaseAuthSettings({ + required this.appVerificationDisabledForTesting, + this.userAccessGroup, + this.phoneNumber, + this.smsCode, + this.forceRecaptchaFlow, + }); + + bool appVerificationDisabledForTesting; + + String? userAccessGroup; + + String? phoneNumber; + + String? smsCode; + + bool? forceRecaptchaFlow; + + Object encode() { + return [ + appVerificationDisabledForTesting, + userAccessGroup, + phoneNumber, + smsCode, + forceRecaptchaFlow, + ]; + } + + static PigeonFirebaseAuthSettings decode(Object result) { + result as List; + return PigeonFirebaseAuthSettings( + appVerificationDisabledForTesting: result[0]! as bool, + userAccessGroup: result[1] as String?, + phoneNumber: result[2] as String?, + smsCode: result[3] as String?, + forceRecaptchaFlow: result[4] as bool?, + ); + } +} + +class PigeonSignInProvider { + PigeonSignInProvider({ + required this.providerId, + this.scopes, + this.customParameters, + }); + + String providerId; + + List? scopes; + + Map? customParameters; + + Object encode() { + return [ + providerId, + scopes, + customParameters, + ]; + } + + static PigeonSignInProvider decode(Object result) { + result as List; + return PigeonSignInProvider( + providerId: result[0]! as String, + scopes: (result[1] as List?)?.cast(), + customParameters: + (result[2] as Map?)?.cast(), + ); + } +} + +class PigeonVerifyPhoneNumberRequest { + PigeonVerifyPhoneNumberRequest({ + this.phoneNumber, + required this.timeout, + this.forceResendingToken, + this.autoRetrievedSmsCodeForTesting, + this.multiFactorInfoId, + this.multiFactorSessionId, + }); + + String? phoneNumber; + + int timeout; + + int? forceResendingToken; + + String? autoRetrievedSmsCodeForTesting; + + String? multiFactorInfoId; + + String? multiFactorSessionId; + + Object encode() { + return [ + phoneNumber, + timeout, + forceResendingToken, + autoRetrievedSmsCodeForTesting, + multiFactorInfoId, + multiFactorSessionId, + ]; + } + + static PigeonVerifyPhoneNumberRequest decode(Object result) { + result as List; + return PigeonVerifyPhoneNumberRequest( + phoneNumber: result[0] as String?, + timeout: result[1]! as int, + forceResendingToken: result[2] as int?, + autoRetrievedSmsCodeForTesting: result[3] as String?, + multiFactorInfoId: result[4] as String?, + multiFactorSessionId: result[5] as String?, + ); + } +} + +class PigeonIdTokenResult { + PigeonIdTokenResult({ + this.token, + this.expirationTimestamp, + this.authTimestamp, + this.issuedAtTimestamp, + this.signInProvider, + this.claims, + this.signInSecondFactor, + }); + + String? token; + + int? expirationTimestamp; + + int? authTimestamp; + + int? issuedAtTimestamp; + + String? signInProvider; + + Map? claims; + + String? signInSecondFactor; + + Object encode() { + return [ + token, + expirationTimestamp, + authTimestamp, + issuedAtTimestamp, + signInProvider, + claims, + signInSecondFactor, + ]; + } + + static PigeonIdTokenResult decode(Object result) { + result as List; + return PigeonIdTokenResult( + token: result[0] as String?, + expirationTimestamp: result[1] as int?, + authTimestamp: result[2] as int?, + issuedAtTimestamp: result[3] as int?, + signInProvider: result[4] as String?, + claims: (result[5] as Map?)?.cast(), + signInSecondFactor: result[6] as String?, + ); + } +} + +class PigeonUserProfile { + PigeonUserProfile({ + this.displayName, + this.photoUrl, + required this.displayNameChanged, + required this.photoUrlChanged, + }); + + String? displayName; + + String? photoUrl; + + bool displayNameChanged; + + bool photoUrlChanged; + + Object encode() { + return [ + displayName, + photoUrl, + displayNameChanged, + photoUrlChanged, + ]; + } + + static PigeonUserProfile decode(Object result) { + result as List; + return PigeonUserProfile( + displayName: result[0] as String?, + photoUrl: result[1] as String?, + displayNameChanged: result[2]! as bool, + photoUrlChanged: result[3]! as bool, + ); + } +} + +class _FirebaseAuthHostApiCodec extends StandardMessageCodec { + const _FirebaseAuthHostApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonActionCodeInfo) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else if (value is PigeonActionCodeInfoData) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else if (value is PigeonActionCodeSettings) { + buffer.putUint8(130); + writeValue(buffer, value.encode()); + } else if (value is PigeonAdditionalUserInfo) { + buffer.putUint8(131); + writeValue(buffer, value.encode()); + } else if (value is PigeonAuthCredential) { + buffer.putUint8(132); + writeValue(buffer, value.encode()); + } else if (value is PigeonFirebaseApp) { + buffer.putUint8(133); + writeValue(buffer, value.encode()); + } else if (value is PigeonFirebaseAuthSettings) { + buffer.putUint8(134); + writeValue(buffer, value.encode()); + } else if (value is PigeonIdTokenResult) { + buffer.putUint8(135); + writeValue(buffer, value.encode()); + } else if (value is PigeonMultiFactorInfo) { + buffer.putUint8(136); + writeValue(buffer, value.encode()); + } else if (value is PigeonMultiFactorSession) { + buffer.putUint8(137); + writeValue(buffer, value.encode()); + } else if (value is PigeonPhoneMultiFactorAssertion) { + buffer.putUint8(138); + writeValue(buffer, value.encode()); + } else if (value is PigeonSignInProvider) { + buffer.putUint8(139); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserCredential) { + buffer.putUint8(140); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserDetails) { + buffer.putUint8(141); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserInfo) { + buffer.putUint8(142); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserProfile) { + buffer.putUint8(143); + writeValue(buffer, value.encode()); + } else if (value is PigeonVerifyPhoneNumberRequest) { + buffer.putUint8(144); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return PigeonActionCodeInfo.decode(readValue(buffer)!); + case 129: + return PigeonActionCodeInfoData.decode(readValue(buffer)!); + case 130: + return PigeonActionCodeSettings.decode(readValue(buffer)!); + case 131: + return PigeonAdditionalUserInfo.decode(readValue(buffer)!); + case 132: + return PigeonAuthCredential.decode(readValue(buffer)!); + case 133: + return PigeonFirebaseApp.decode(readValue(buffer)!); + case 134: + return PigeonFirebaseAuthSettings.decode(readValue(buffer)!); + case 135: + return PigeonIdTokenResult.decode(readValue(buffer)!); + case 136: + return PigeonMultiFactorInfo.decode(readValue(buffer)!); + case 137: + return PigeonMultiFactorSession.decode(readValue(buffer)!); + case 138: + return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); + case 139: + return PigeonSignInProvider.decode(readValue(buffer)!); + case 140: + return PigeonUserCredential.decode(readValue(buffer)!); + case 141: + return PigeonUserDetails.decode(readValue(buffer)!); + case 142: + return PigeonUserInfo.decode(readValue(buffer)!); + case 143: + return PigeonUserProfile.decode(readValue(buffer)!); + case 144: + return PigeonVerifyPhoneNumberRequest.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +class FirebaseAuthHostApi { + /// Constructor for [FirebaseAuthHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + FirebaseAuthHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _FirebaseAuthHostApiCodec(); + + Future registerIdTokenListener(PigeonFirebaseApp arg_app) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.registerIdTokenListener', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as String?)!; + } + } + + Future registerAuthStateListener(PigeonFirebaseApp arg_app) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.registerAuthStateListener', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as String?)!; + } + } + + Future useEmulator( + PigeonFirebaseApp arg_app, String arg_host, int arg_port) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.useEmulator', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_host, arg_port]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future applyActionCode( + PigeonFirebaseApp arg_app, String arg_code) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.applyActionCode', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app, arg_code]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future checkActionCode( + PigeonFirebaseApp arg_app, String arg_code) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.checkActionCode', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app, arg_code]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonActionCodeInfo?)!; + } + } + + Future confirmPasswordReset(PigeonFirebaseApp arg_app, String arg_code, + String arg_newPassword) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.confirmPasswordReset', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_code, arg_newPassword]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future createUserWithEmailAndPassword( + PigeonFirebaseApp arg_app, String arg_email, String arg_password) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.createUserWithEmailAndPassword', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_email, arg_password]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserCredential?)!; + } + } + + Future signInAnonymously( + PigeonFirebaseApp arg_app) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.signInAnonymously', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserCredential?)!; + } + } + + Future signInWithCredential( + PigeonFirebaseApp arg_app, Map arg_input) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.signInWithCredential', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app, arg_input]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserCredential?)!; + } + } + + Future signInWithCustomToken( + PigeonFirebaseApp arg_app, String arg_token) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.signInWithCustomToken', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app, arg_token]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserCredential?)!; + } + } + + Future signInWithEmailAndPassword( + PigeonFirebaseApp arg_app, String arg_email, String arg_password) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailAndPassword', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_email, arg_password]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserCredential?)!; + } + } + + Future signInWithEmailLink( + PigeonFirebaseApp arg_app, String arg_email, String arg_emailLink) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailLink', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_email, arg_emailLink]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserCredential?)!; + } + } + + Future signInWithProvider(PigeonFirebaseApp arg_app, + PigeonSignInProvider arg_signInProvider) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.signInWithProvider', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_signInProvider]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserCredential?)!; + } + } + + Future signOut(PigeonFirebaseApp arg_app) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.signOut', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future> fetchSignInMethodsForEmail( + PigeonFirebaseApp arg_app, String arg_email) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.fetchSignInMethodsForEmail', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app, arg_email]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as List?)!.cast(); + } + } + + Future sendPasswordResetEmail( + PigeonFirebaseApp arg_app, + String arg_email, + PigeonActionCodeSettings? arg_actionCodeSettings) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.sendPasswordResetEmail', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_email, arg_actionCodeSettings]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future sendSignInLinkToEmail(PigeonFirebaseApp arg_app, + String arg_email, PigeonActionCodeSettings arg_actionCodeSettings) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.sendSignInLinkToEmail', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_email, arg_actionCodeSettings]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setLanguageCode( + PigeonFirebaseApp arg_app, String? arg_languageCode) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.setLanguageCode', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_languageCode]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as String?)!; + } + } + + Future setSettings(PigeonFirebaseApp arg_app, + PigeonFirebaseAuthSettings arg_settings) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.setSettings', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app, arg_settings]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future verifyPasswordResetCode( + PigeonFirebaseApp arg_app, String arg_code) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.verifyPasswordResetCode', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app, arg_code]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as String?)!; + } + } + + Future verifyPhoneNumber(PigeonFirebaseApp arg_app, + PigeonVerifyPhoneNumberRequest arg_request) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.verifyPhoneNumber', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app, arg_request]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as String?)!; + } + } +} + +class _FirebaseAuthUserHostApiCodec extends StandardMessageCodec { + const _FirebaseAuthUserHostApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonActionCodeInfo) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else if (value is PigeonActionCodeInfoData) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else if (value is PigeonActionCodeSettings) { + buffer.putUint8(130); + writeValue(buffer, value.encode()); + } else if (value is PigeonAdditionalUserInfo) { + buffer.putUint8(131); + writeValue(buffer, value.encode()); + } else if (value is PigeonAuthCredential) { + buffer.putUint8(132); + writeValue(buffer, value.encode()); + } else if (value is PigeonFirebaseApp) { + buffer.putUint8(133); + writeValue(buffer, value.encode()); + } else if (value is PigeonFirebaseAuthSettings) { + buffer.putUint8(134); + writeValue(buffer, value.encode()); + } else if (value is PigeonIdTokenResult) { + buffer.putUint8(135); + writeValue(buffer, value.encode()); + } else if (value is PigeonMultiFactorInfo) { + buffer.putUint8(136); + writeValue(buffer, value.encode()); + } else if (value is PigeonMultiFactorSession) { + buffer.putUint8(137); + writeValue(buffer, value.encode()); + } else if (value is PigeonPhoneMultiFactorAssertion) { + buffer.putUint8(138); + writeValue(buffer, value.encode()); + } else if (value is PigeonSignInProvider) { + buffer.putUint8(139); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserCredential) { + buffer.putUint8(140); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserDetails) { + buffer.putUint8(141); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserInfo) { + buffer.putUint8(142); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserProfile) { + buffer.putUint8(143); + writeValue(buffer, value.encode()); + } else if (value is PigeonVerifyPhoneNumberRequest) { + buffer.putUint8(144); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return PigeonActionCodeInfo.decode(readValue(buffer)!); + case 129: + return PigeonActionCodeInfoData.decode(readValue(buffer)!); + case 130: + return PigeonActionCodeSettings.decode(readValue(buffer)!); + case 131: + return PigeonAdditionalUserInfo.decode(readValue(buffer)!); + case 132: + return PigeonAuthCredential.decode(readValue(buffer)!); + case 133: + return PigeonFirebaseApp.decode(readValue(buffer)!); + case 134: + return PigeonFirebaseAuthSettings.decode(readValue(buffer)!); + case 135: + return PigeonIdTokenResult.decode(readValue(buffer)!); + case 136: + return PigeonMultiFactorInfo.decode(readValue(buffer)!); + case 137: + return PigeonMultiFactorSession.decode(readValue(buffer)!); + case 138: + return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); + case 139: + return PigeonSignInProvider.decode(readValue(buffer)!); + case 140: + return PigeonUserCredential.decode(readValue(buffer)!); + case 141: + return PigeonUserDetails.decode(readValue(buffer)!); + case 142: + return PigeonUserInfo.decode(readValue(buffer)!); + case 143: + return PigeonUserProfile.decode(readValue(buffer)!); + case 144: + return PigeonVerifyPhoneNumberRequest.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +class FirebaseAuthUserHostApi { + /// Constructor for [FirebaseAuthUserHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + FirebaseAuthUserHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _FirebaseAuthUserHostApiCodec(); + + Future delete(PigeonFirebaseApp arg_app) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.delete', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } -import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer; -import 'package:flutter/services.dart'; + Future getIdToken( + PigeonFirebaseApp arg_app, bool arg_forceRefresh) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.getIdToken', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_forceRefresh]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonIdTokenResult?)!; + } + } -class PigeonMultiFactorSession { - PigeonMultiFactorSession({ - required this.id, - }); + Future linkWithCredential( + PigeonFirebaseApp arg_app, Map arg_input) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.linkWithCredential', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app, arg_input]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserCredential?)!; + } + } - String id; + Future linkWithProvider(PigeonFirebaseApp arg_app, + PigeonSignInProvider arg_signInProvider) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.linkWithProvider', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_signInProvider]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserCredential?)!; + } + } - Object encode() { - final Map pigeonMap = {}; - pigeonMap['id'] = id; - return pigeonMap; + Future reauthenticateWithCredential( + PigeonFirebaseApp arg_app, Map arg_input) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.reauthenticateWithCredential', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app, arg_input]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserCredential?)!; + } } - static PigeonMultiFactorSession decode(Object message) { - final Map pigeonMap = message as Map; - return PigeonMultiFactorSession( - id: pigeonMap['id']! as String, - ); + Future reauthenticateWithProvider( + PigeonFirebaseApp arg_app, + PigeonSignInProvider arg_signInProvider) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.reauthenticateWithProvider', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_signInProvider]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserCredential?)!; + } } -} -class PigeonPhoneMultiFactorAssertion { - PigeonPhoneMultiFactorAssertion({ - required this.verificationId, - required this.verificationCode, - }); + Future reload(PigeonFirebaseApp arg_app) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.reload', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserDetails?)!; + } + } - String verificationId; - String verificationCode; + Future sendEmailVerification(PigeonFirebaseApp arg_app, + PigeonActionCodeSettings? arg_actionCodeSettings) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.sendEmailVerification', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_actionCodeSettings]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } - Object encode() { - final Map pigeonMap = {}; - pigeonMap['verificationId'] = verificationId; - pigeonMap['verificationCode'] = verificationCode; - return pigeonMap; + Future unlink( + PigeonFirebaseApp arg_app, String arg_providerId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.unlink', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_providerId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserCredential?)!; + } } - static PigeonPhoneMultiFactorAssertion decode(Object message) { - final Map pigeonMap = message as Map; - return PigeonPhoneMultiFactorAssertion( - verificationId: pigeonMap['verificationId']! as String, - verificationCode: pigeonMap['verificationCode']! as String, - ); + Future updateEmail( + PigeonFirebaseApp arg_app, String arg_newEmail) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.updateEmail', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app, arg_newEmail]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserDetails?)!; + } } -} -class PigeonMultiFactorInfo { - PigeonMultiFactorInfo({ - this.displayName, - required this.enrollmentTimestamp, - this.factorId, - required this.uid, - this.phoneNumber, - }); + Future updatePassword( + PigeonFirebaseApp arg_app, String arg_newPassword) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.updatePassword', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_newPassword]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserDetails?)!; + } + } - String? displayName; - double enrollmentTimestamp; - String? factorId; - String uid; - String? phoneNumber; + Future updatePhoneNumber( + PigeonFirebaseApp arg_app, Map arg_input) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.updatePhoneNumber', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app, arg_input]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserDetails?)!; + } + } - Object encode() { - final Map pigeonMap = {}; - pigeonMap['displayName'] = displayName; - pigeonMap['enrollmentTimestamp'] = enrollmentTimestamp; - pigeonMap['factorId'] = factorId; - pigeonMap['uid'] = uid; - pigeonMap['phoneNumber'] = phoneNumber; - return pigeonMap; + Future updateProfile( + PigeonFirebaseApp arg_app, PigeonUserProfile arg_profile) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.updateProfile', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_app, arg_profile]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonUserDetails?)!; + } } - static PigeonMultiFactorInfo decode(Object message) { - final Map pigeonMap = message as Map; - return PigeonMultiFactorInfo( - displayName: pigeonMap['displayName'] as String?, - enrollmentTimestamp: pigeonMap['enrollmentTimestamp']! as double, - factorId: pigeonMap['factorId'] as String?, - uid: pigeonMap['uid']! as String, - phoneNumber: pigeonMap['phoneNumber'] as String?, - ); + Future verifyBeforeUpdateEmail( + PigeonFirebaseApp arg_app, + String arg_newEmail, + PigeonActionCodeSettings? arg_actionCodeSettings) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.verifyBeforeUpdateEmail', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_app, arg_newEmail, arg_actionCodeSettings]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } } } @@ -98,15 +1845,18 @@ class _MultiFactorUserHostApiCodec extends StandardMessageCodec { const _MultiFactorUserHostApiCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonMultiFactorInfo) { + if (value is PigeonFirebaseApp) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorSession) { + } else if (value is PigeonMultiFactorInfo) { buffer.putUint8(129); writeValue(buffer, value.encode()); - } else if (value is PigeonPhoneMultiFactorAssertion) { + } else if (value is PigeonMultiFactorSession) { buffer.putUint8(130); writeValue(buffer, value.encode()); + } else if (value is PigeonPhoneMultiFactorAssertion) { + buffer.putUint8(131); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -116,14 +1866,13 @@ class _MultiFactorUserHostApiCodec extends StandardMessageCodec { Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { case 128: - return PigeonMultiFactorInfo.decode(readValue(buffer)!); - + return PigeonFirebaseApp.decode(readValue(buffer)!); case 129: - return PigeonMultiFactorSession.decode(readValue(buffer)!); - + return PigeonMultiFactorInfo.decode(readValue(buffer)!); case 130: + return PigeonMultiFactorSession.decode(readValue(buffer)!); + case 131: return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); - default: return super.readValueOfType(type, buffer); } @@ -136,86 +1885,79 @@ class MultiFactorUserHostApi { /// BinaryMessenger will be used which routes to the host platform. MultiFactorUserHostApi({BinaryMessenger? binaryMessenger}) : _binaryMessenger = binaryMessenger; - final BinaryMessenger? _binaryMessenger; static const MessageCodec codec = _MultiFactorUserHostApiCodec(); Future enrollPhone( - String arg_appName, + PigeonFirebaseApp arg_app, PigeonPhoneMultiFactorAssertion arg_assertion, String? arg_displayName) async { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.MultiFactorUserHostApi.enrollPhone', codec, binaryMessenger: _binaryMessenger); - final Map? replyMap = await channel - .send([arg_appName, arg_assertion, arg_displayName]) - as Map?; - if (replyMap == null) { + final List? replyList = + await channel.send([arg_app, arg_assertion, arg_displayName]) + as List?; + if (replyList == null) { throw PlatformException( code: 'channel-error', message: 'Unable to establish connection on channel.', ); - } else if (replyMap['error'] != null) { - final Map error = - (replyMap['error'] as Map?)!; + } else if (replyList.length > 1) { throw PlatformException( - code: (error['code'] as String?)!, - message: error['message'] as String?, - details: error['details'], + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], ); } else { return; } } - Future getSession(String arg_appName) async { + Future getSession(PigeonFirebaseApp arg_app) async { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.MultiFactorUserHostApi.getSession', codec, binaryMessenger: _binaryMessenger); - final Map? replyMap = - await channel.send([arg_appName]) as Map?; - if (replyMap == null) { + final List? replyList = + await channel.send([arg_app]) as List?; + if (replyList == null) { throw PlatformException( code: 'channel-error', message: 'Unable to establish connection on channel.', ); - } else if (replyMap['error'] != null) { - final Map error = - (replyMap['error'] as Map?)!; + } else if (replyList.length > 1) { throw PlatformException( - code: (error['code'] as String?)!, - message: error['message'] as String?, - details: error['details'], + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], ); - } else if (replyMap['result'] == null) { + } else if (replyList[0] == null) { throw PlatformException( code: 'null-error', message: 'Host platform returned null value for non-null return value.', ); } else { - return (replyMap['result'] as PigeonMultiFactorSession?)!; + return (replyList[0] as PigeonMultiFactorSession?)!; } } - Future unenroll(String arg_appName, String? arg_factorUid) async { + Future unenroll(PigeonFirebaseApp arg_app, String arg_factorUid) async { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.MultiFactorUserHostApi.unenroll', codec, binaryMessenger: _binaryMessenger); - final Map? replyMap = await channel - .send([arg_appName, arg_factorUid]) as Map?; - if (replyMap == null) { + final List? replyList = + await channel.send([arg_app, arg_factorUid]) as List?; + if (replyList == null) { throw PlatformException( code: 'channel-error', message: 'Unable to establish connection on channel.', ); - } else if (replyMap['error'] != null) { - final Map error = - (replyMap['error'] as Map?)!; + } else if (replyList.length > 1) { throw PlatformException( - code: (error['code'] as String?)!, - message: error['message'] as String?, - details: error['details'], + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], ); } else { return; @@ -223,33 +1965,30 @@ class MultiFactorUserHostApi { } Future> getEnrolledFactors( - String arg_appName) async { + PigeonFirebaseApp arg_app) async { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.MultiFactorUserHostApi.getEnrolledFactors', codec, binaryMessenger: _binaryMessenger); - final Map? replyMap = - await channel.send([arg_appName]) as Map?; - if (replyMap == null) { + final List? replyList = + await channel.send([arg_app]) as List?; + if (replyList == null) { throw PlatformException( code: 'channel-error', message: 'Unable to establish connection on channel.', ); - } else if (replyMap['error'] != null) { - final Map error = - (replyMap['error'] as Map?)!; + } else if (replyList.length > 1) { throw PlatformException( - code: (error['code'] as String?)!, - message: error['message'] as String?, - details: error['details'], + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], ); - } else if (replyMap['result'] == null) { + } else if (replyList[0] == null) { throw PlatformException( code: 'null-error', message: 'Host platform returned null value for non-null return value.', ); } else { - return (replyMap['result'] as List?)! - .cast(); + return (replyList[0] as List?)!.cast(); } } } @@ -258,15 +1997,24 @@ class _MultiFactoResolverHostApiCodec extends StandardMessageCodec { const _MultiFactoResolverHostApiCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonMultiFactorInfo) { + if (value is PigeonAdditionalUserInfo) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorSession) { + } else if (value is PigeonAuthCredential) { buffer.putUint8(129); writeValue(buffer, value.encode()); } else if (value is PigeonPhoneMultiFactorAssertion) { buffer.putUint8(130); writeValue(buffer, value.encode()); + } else if (value is PigeonUserCredential) { + buffer.putUint8(131); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserDetails) { + buffer.putUint8(132); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserInfo) { + buffer.putUint8(133); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -276,14 +2024,17 @@ class _MultiFactoResolverHostApiCodec extends StandardMessageCodec { Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { case 128: - return PigeonMultiFactorInfo.decode(readValue(buffer)!); - + return PigeonAdditionalUserInfo.decode(readValue(buffer)!); case 129: - return PigeonMultiFactorSession.decode(readValue(buffer)!); - + return PigeonAuthCredential.decode(readValue(buffer)!); case 130: return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); - + case 131: + return PigeonUserCredential.decode(readValue(buffer)!); + case 132: + return PigeonUserDetails.decode(readValue(buffer)!); + case 133: + return PigeonUserInfo.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); } @@ -296,40 +2047,35 @@ class MultiFactoResolverHostApi { /// BinaryMessenger will be used which routes to the host platform. MultiFactoResolverHostApi({BinaryMessenger? binaryMessenger}) : _binaryMessenger = binaryMessenger; - final BinaryMessenger? _binaryMessenger; static const MessageCodec codec = _MultiFactoResolverHostApiCodec(); - Future> resolveSignIn(String arg_resolverId, + Future resolveSignIn(String arg_resolverId, PigeonPhoneMultiFactorAssertion arg_assertion) async { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.MultiFactoResolverHostApi.resolveSignIn', codec, binaryMessenger: _binaryMessenger); - final Map? replyMap = - await channel.send([arg_resolverId, arg_assertion]) - as Map?; - if (replyMap == null) { + final List? replyList = await channel + .send([arg_resolverId, arg_assertion]) as List?; + if (replyList == null) { throw PlatformException( code: 'channel-error', message: 'Unable to establish connection on channel.', ); - } else if (replyMap['error'] != null) { - final Map error = - (replyMap['error'] as Map?)!; + } else if (replyList.length > 1) { throw PlatformException( - code: (error['code'] as String?)!, - message: error['message'] as String?, - details: error['details'], + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], ); - } else if (replyMap['result'] == null) { + } else if (replyList[0] == null) { throw PlatformException( code: 'null-error', message: 'Host platform returned null value for non-null return value.', ); } else { - return (replyMap['result'] as Map?)! - .cast(); + return (replyList[0] as PigeonUserCredential?)!; } } } @@ -351,20 +2097,19 @@ class _GenerateInterfacesCodec extends StandardMessageCodec { switch (type) { case 128: return PigeonMultiFactorInfo.decode(readValue(buffer)!); - default: return super.readValueOfType(type, buffer); } } } +/// Only used to generate the object interface that are use outside of the Pigeon interface class GenerateInterfaces { /// Constructor for [GenerateInterfaces]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. GenerateInterfaces({BinaryMessenger? binaryMessenger}) : _binaryMessenger = binaryMessenger; - final BinaryMessenger? _binaryMessenger; static const MessageCodec codec = _GenerateInterfacesCodec(); @@ -373,20 +2118,18 @@ class GenerateInterfaces { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.GenerateInterfaces.generateInterfaces', codec, binaryMessenger: _binaryMessenger); - final Map? replyMap = - await channel.send([arg_info]) as Map?; - if (replyMap == null) { + final List? replyList = + await channel.send([arg_info]) as List?; + if (replyList == null) { throw PlatformException( code: 'channel-error', message: 'Unable to establish connection on channel.', ); - } else if (replyMap['error'] != null) { - final Map error = - (replyMap['error'] as Map?)!; + } else if (replyList.length > 1) { throw PlatformException( - code: (error['code'] as String?)!, - message: error['message'] as String?, - details: error['details'], + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], ); } else { return; diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart index 2d47eeb6fb37..0be8aa010cbf 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart @@ -48,18 +48,23 @@ abstract class FirebaseAuthPlatform extends PlatformInterface { static final Object _token = Object(); /// Create an instance using [app] using the existing implementation - factory FirebaseAuthPlatform.instanceFor( - {required FirebaseApp app, - required Map pluginConstants, - Persistence? persistence}) { + factory FirebaseAuthPlatform.instanceFor({ + required FirebaseApp app, + required Map pluginConstants, + Persistence? persistence, + }) { + var currentUser = pluginConstants['APP_CURRENT_USER']; + + if (currentUser != null) { + currentUser as List; + currentUser = PigeonUserDetails.decode(currentUser); + } return FirebaseAuthPlatform.instance .delegateFor(app: app, persistence: persistence) .setInitialValues( - languageCode: pluginConstants['APP_LANGUAGE_CODE'], - currentUser: pluginConstants['APP_CURRENT_USER'] == null - ? null - : Map.from( - pluginConstants['APP_CURRENT_USER'])); + languageCode: pluginConstants['APP_LANGUAGE_CODE'], + currentUser: currentUser, + ); } /// The current default [FirebaseAuthPlatform] instance. @@ -96,7 +101,7 @@ abstract class FirebaseAuthPlatform extends PlatformInterface { /// calls. @protected FirebaseAuthPlatform setInitialValues({ - Map? currentUser, + PigeonUserDetails? currentUser, String? languageCode, }) { throw UnimplementedError('setInitialValues() is not implemented'); @@ -366,7 +371,7 @@ abstract class FirebaseAuthPlatform extends PlatformInterface { /// settings > Capabilities). To learn more, visit the /// [Apple documentation](https://developer.apple.com/documentation/security/keychain_services/keychain_items/sharing_access_to_keychain_items_among_a_collection_of_apps). Future setSettings({ - bool? appVerificationDisabledForTesting, + bool appVerificationDisabledForTesting = false, String? userAccessGroup, String? phoneNumber, String? smsCode, diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_user.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_user.dart index e23384156b71..d78eee1c4851 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_user.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_user.dart @@ -5,13 +5,14 @@ import 'dart:async'; +import 'package:collection/collection.dart'; import 'package:firebase_auth_platform_interface/firebase_auth_platform_interface.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; /// A user account. abstract class UserPlatform extends PlatformInterface { // ignore: public_member_api_docs - UserPlatform(this.auth, this.multiFactor, Map user) + UserPlatform(this.auth, this.multiFactor, PigeonUserDetails user) : _user = user, super(token: _token); @@ -27,20 +28,20 @@ abstract class UserPlatform extends PlatformInterface { final MultiFactorPlatform multiFactor; - final Map _user; + final PigeonUserDetails _user; /// The users display name. /// /// Will be `null` if signing in anonymously or via password authentication. String? get displayName { - return _user['displayName']; + return _user.userInfo.displayName; } /// The users email address. /// /// Will be `null` if signing in anonymously. String? get email { - return _user['email']; + return _user.userInfo.email; } /// Returns whether the users email address has been verified. @@ -49,19 +50,21 @@ abstract class UserPlatform extends PlatformInterface { /// /// Once verified, call [reload] to ensure the latest user information is /// retrieved from Firebase. - bool get emailVerified { - return _user['emailVerified']; + bool get isEmailVerified { + return _user.userInfo.isEmailVerified; } /// Returns whether the user is a anonymous. bool get isAnonymous { - return _user['isAnonymous']; + return _user.userInfo.isAnonymous; } /// Returns additional metadata about the user, such as their creation time. UserMetadata get metadata { return UserMetadata( - _user['metadata']['creationTime'], _user['metadata']['lastSignInTime']); + _user.userInfo.creationTimestamp, + _user.userInfo.lastSignInTimestamp, + ); } /// Returns the users phone number. @@ -69,7 +72,7 @@ abstract class UserPlatform extends PlatformInterface { /// This property will be `null` if the user has not signed in or been has /// their phone number linked. String? get phoneNumber { - return _user['phoneNumber']; + return _user.userInfo.phoneNumber; } /// Returns a photo URL for the user. @@ -77,14 +80,17 @@ abstract class UserPlatform extends PlatformInterface { /// This property will be populated if the user has signed in or been linked /// with a 3rd party OAuth provider (such as Google). String? get photoURL { - return _user['photoURL']; + return _user.userInfo.photoUrl; } /// Returns a list of user information for each linked provider. List get providerData { - return List.from(_user['providerData']) - .map((data) => UserInfo(Map.from(data))) - .toList(); + final inputData = _user.providerData.whereNotNull(); + final List providerData = []; + for (final Map info in inputData) { + providerData.add(UserInfo.fromJson(info)); + } + return providerData; } /// Returns a JWT refresh token for the user. @@ -92,7 +98,7 @@ abstract class UserPlatform extends PlatformInterface { /// This property will be an empty string for native platforms (android, iOS & macOS) as they do not /// support refresh tokens. String? get refreshToken { - return _user['refreshToken']; + return _user.userInfo.refreshToken; } /// The current user's tenant ID. @@ -101,12 +107,12 @@ abstract class UserPlatform extends PlatformInterface { /// in the current user. This is `null` if the user is signed in from the /// parent project. String? get tenantId { - return _user['tenantId']; + return _user.userInfo.tenantId; } /// The user's unique ID. String get uid { - return _user['uid']; + return _user.userInfo.uid; } /// Deletes and signs out the user. @@ -132,7 +138,7 @@ abstract class UserPlatform extends PlatformInterface { /// /// If [forceRefresh] is `true`, the token returned will be refresh regardless /// of token expiration. - Future getIdToken(bool forceRefresh) { + Future getIdToken(bool forceRefresh) { throw UnimplementedError('getIdToken() is not implemented'); } diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/apple_auth.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/apple_auth.dart index 546825319e25..e1e77e64995e 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/apple_auth.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/apple_auth.dart @@ -57,7 +57,7 @@ class AppleAuthProvider extends AuthProvider { } List _scopes = []; - Map _parameters = {}; + Map _parameters = {}; /// Returns the currently assigned scopes to this provider instance. List get scopes { @@ -65,7 +65,7 @@ class AppleAuthProvider extends AuthProvider { } /// Returns the parameters for this provider instance. - Map get parameters { + Map get parameters { return _parameters; } @@ -78,7 +78,7 @@ class AppleAuthProvider extends AuthProvider { /// Sets the OAuth custom parameters to pass in a Apple OAuth /// request for popup and redirect sign-in operations. AppleAuthProvider setCustomParameters( - Map customOAuthParameters, + Map customOAuthParameters, ) { _parameters = customOAuthParameters; return this; diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/github_auth.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/github_auth.dart index 55af5f966174..a420ee2169c2 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/github_auth.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/github_auth.dart @@ -57,7 +57,7 @@ class GithubAuthProvider extends AuthProvider { } List _scopes = []; - Map _parameters = {}; + Map _parameters = {}; /// Returns the currently assigned scopes to this provider instance. List get scopes { @@ -65,7 +65,7 @@ class GithubAuthProvider extends AuthProvider { } /// Returns the parameters for this provider instance. - Map get parameters { + Map get parameters { return _parameters; } @@ -78,7 +78,7 @@ class GithubAuthProvider extends AuthProvider { /// Sets the OAuth custom parameters to pass in a GitHub OAuth /// request for popup and redirect sign-in operations. GithubAuthProvider setCustomParameters( - Map customOAuthParameters, + Map customOAuthParameters, ) { _parameters = customOAuthParameters; return this; diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/microsoft_auth.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/microsoft_auth.dart index c60c6f7469ad..8f6bdb0af835 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/microsoft_auth.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/microsoft_auth.dart @@ -57,7 +57,7 @@ class MicrosoftAuthProvider extends AuthProvider { } List _scopes = []; - Map _parameters = {}; + Map _parameters = {}; /// Returns the currently assigned scopes to this provider instance. List get scopes { @@ -65,7 +65,7 @@ class MicrosoftAuthProvider extends AuthProvider { } /// Returns the parameters for this provider instance. - Map get parameters { + Map get parameters { return _parameters; } @@ -78,7 +78,7 @@ class MicrosoftAuthProvider extends AuthProvider { /// Sets the OAuth custom parameters to pass in a Microsoft OAuth /// request for popup and redirect sign-in operations. MicrosoftAuthProvider setCustomParameters( - Map customOAuthParameters, + Map customOAuthParameters, ) { _parameters = customOAuthParameters; return this; diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/oauth.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/oauth.dart index 3da8705a5279..be975bee57ba 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/oauth.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/oauth.dart @@ -15,7 +15,7 @@ class OAuthProvider extends AuthProvider { OAuthProvider(String providerId) : super(providerId); List _scopes = []; - Map _parameters = {}; + Map _parameters = {}; /// Returns the currently assigned scopes to this provider instance. List get scopes { @@ -23,7 +23,7 @@ class OAuthProvider extends AuthProvider { } /// Returns the parameters for this provider instance. - Map get parameters { + Map get parameters { return _parameters; } @@ -42,7 +42,7 @@ class OAuthProvider extends AuthProvider { /// Sets the OAuth custom parameters to pass in a OAuth request for popup and /// redirect sign-in operations. OAuthProvider setCustomParameters( - Map customOAuthParameters, + Map customOAuthParameters, ) { _parameters = customOAuthParameters; return this; diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/twitter_auth.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/twitter_auth.dart index 6151e6648fda..7408db0a1fe6 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/twitter_auth.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/providers/twitter_auth.dart @@ -61,17 +61,17 @@ class TwitterAuthProvider extends AuthProvider { return _kProviderId; } - Map _parameters = {}; + Map _parameters = {}; /// Returns the parameters for this provider instance. - Map get parameters { + Map get parameters { return _parameters; } /// Sets the OAuth custom parameters to pass in a Twitter OAuth request for /// popup and redirect sign-in operations. TwitterAuthProvider setCustomParameters( - Map customOAuthParameters, + Map customOAuthParameters, ) { _parameters = customOAuthParameters; return this; diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/user_info.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/user_info.dart index 6e94f253ed8b..ddccb0f8cded 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/user_info.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/user_info.dart @@ -3,28 +3,46 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart'; import 'package:meta/meta.dart'; /// User profile information, visible only to the Firebase project's apps. class UserInfo { // ignore: public_member_api_docs @protected - UserInfo(this._data); + UserInfo.fromPigeon(this._data); - final Map _data; + @protected + UserInfo.fromJson(Map data) + : _data = PigeonUserInfo( + uid: data['uid'] as String, + email: data['email'] as String?, + displayName: data['displayName'] as String?, + photoUrl: data['photoUrl'] as String?, + phoneNumber: data['phoneNumber'] as String?, + isAnonymous: data['isAnonymous'] as bool, + isEmailVerified: data['isEmailVerified'] as bool, + providerId: data['providerId'] as String?, + tenantId: data['tenantId'] as String?, + refreshToken: data['refreshToken'] as String?, + creationTimestamp: data['creationTimestamp'] as int?, + lastSignInTimestamp: data['lastSignInTimestamp'] as int?, + ); + + final PigeonUserInfo _data; /// The users display name. /// /// Will be `null` if signing in anonymously or via password authentication. String? get displayName { - return _data['displayName']; + return _data.displayName; } /// The users email address. /// /// Will be `null` if signing in anonymously. String? get email { - return _data['email']; + return _data.email; } /// Returns the users phone number. @@ -32,7 +50,7 @@ class UserInfo { /// This property will be `null` if the user has not signed in or been has /// their phone number linked. String? get phoneNumber { - return _data['phoneNumber']; + return _data.phoneNumber; } /// Returns a photo URL for the user. @@ -40,17 +58,18 @@ class UserInfo { /// This property will be populated if the user has signed in or been linked /// with a 3rd party OAuth provider (such as Google). String? get photoURL { - return _data['photoURL']; + return _data.photoUrl; } /// The federated provider ID. String get providerId { - return _data['providerId']!; + // UserInfo objects are only available from providers. + return _data.providerId!; } /// The user's unique ID. String? get uid { - return _data['uid']; + return _data.uid; } @override diff --git a/packages/firebase_auth/firebase_auth_platform_interface/pigeons/messages.dart b/packages/firebase_auth/firebase_auth_platform_interface/pigeons/messages.dart index 3ea434818bc1..b4d8727a64d2 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/pigeons/messages.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/pigeons/messages.dart @@ -55,32 +55,503 @@ class PigeonMultiFactorInfo { final String? phoneNumber; } +class PigeonFirebaseApp { + const PigeonFirebaseApp({ + required this.appName, + required this.tenantId, + }); + + final String appName; + final String? tenantId; +} + +/// The type of operation that generated the action code from calling +/// [checkActionCode]. +enum ActionCodeInfoOperation { + /// Unknown operation. + unknown, + + /// Password reset code generated via [sendPasswordResetEmail]. + passwordReset, + + /// Email verification code generated via [User.sendEmailVerification]. + verifyEmail, + + /// Email change revocation code generated via [User.updateEmail]. + recoverEmail, + + /// Email sign in code generated via [sendSignInLinkToEmail]. + emailSignIn, + + /// Verify and change email code generated via [User.verifyBeforeUpdateEmail]. + verifyAndChangeEmail, + + /// Action code for reverting second factor addition. + revertSecondFactorAddition, +} + +class PigeonActionCodeInfo { + const PigeonActionCodeInfo({ + required this.operation, + required this.data, + }); + + final ActionCodeInfoOperation operation; + final PigeonActionCodeInfoData data; +} + +class PigeonActionCodeInfoData { + const PigeonActionCodeInfoData({ + this.email, + this.previousEmail, + }); + + final String? email; + final String? previousEmail; +} + +class PigeonUserCredential { + const PigeonUserCredential({ + required this.user, + required this.additionalUserInfo, + required this.credential, + }); + + final PigeonUserDetails? user; + final PigeonAdditionalUserInfo? additionalUserInfo; + final PigeonAuthCredential? credential; +} + +class PigeonAdditionalUserInfo { + const PigeonAdditionalUserInfo({ + required this.isNewUser, + required this.providerId, + required this.username, + this.profile, + }); + + final bool isNewUser; + final String? providerId; + final String? username; + final Map? profile; +} + +class PigeonAuthCredential { + const PigeonAuthCredential({ + required this.providerId, + required this.signInMethod, + required this.nativeId, + required this.accessToken, + }); + + final String providerId; + final String signInMethod; + final int nativeId; + final String? accessToken; +} + +class PigeonUserInfo { + const PigeonUserInfo({ + required this.uid, + required this.email, + required this.displayName, + required this.photoUrl, + required this.phoneNumber, + required this.isAnonymous, + required this.isEmailVerified, + required this.tenantId, + required this.providerId, + required this.creationTimestamp, + required this.lastSignInTimestamp, + required this.refreshToken, + }); + + final String uid; + final String? email; + final String? displayName; + final String? photoUrl; + final String? phoneNumber; + final bool isAnonymous; + final bool isEmailVerified; + final String? providerId; + final String? tenantId; + final String? refreshToken; + final int? creationTimestamp; + final int? lastSignInTimestamp; +} + +class PigeonUserDetails { + const PigeonUserDetails({ + required this.userInfo, + required this.providerData, + }); + + final PigeonUserInfo userInfo; + final List?> providerData; +} + +class PigeonAuthCredentialInput { + const PigeonAuthCredentialInput({ + required this.providerId, + required this.signInMethod, + required this.token, + required this.accessToken, + }); + + final String providerId; + final String signInMethod; + final String? token; + final String? accessToken; +} + +class PigeonActionCodeSettings { + const PigeonActionCodeSettings({ + required this.url, + required this.dynamicLinkDomain, + required this.handleCodeInApp, + required this.iOSBundleId, + required this.androidPackageName, + required this.androidInstallApp, + required this.androidMinimumVersion, + }); + + final String url; + final String? dynamicLinkDomain; + final bool handleCodeInApp; + final String? iOSBundleId; + final String? androidPackageName; + final bool androidInstallApp; + final String? androidMinimumVersion; +} + +class PigeonFirebaseAuthSettings { + const PigeonFirebaseAuthSettings({ + required this.appVerificationDisabledForTesting, + required this.userAccessGroup, + required this.phoneNumber, + required this.smsCode, + required this.forceRecaptchaFlow, + }); + + final bool appVerificationDisabledForTesting; + final String? userAccessGroup; + final String? phoneNumber; + final String? smsCode; + final bool? forceRecaptchaFlow; +} + +class PigeonSignInProvider { + const PigeonSignInProvider({ + required this.providerId, + required this.scopes, + required this.customParameters, + }); + + final String providerId; + final List? scopes; + final Map? customParameters; +} + +class PigeonVerifyPhoneNumberRequest { + const PigeonVerifyPhoneNumberRequest({ + required this.phoneNumber, + required this.timeout, + required this.forceResendingToken, + required this.autoRetrievedSmsCodeForTesting, + required this.multiFactorInfoId, + required this.multiFactorSessionId, + }); + + final String? phoneNumber; + final int timeout; + final int? forceResendingToken; + final String? autoRetrievedSmsCodeForTesting; + final String? multiFactorInfoId; + final String? multiFactorSessionId; +} + +@HostApi(dartHostTestHandler: 'TestFirebaseAuthHostApi') +abstract class FirebaseAuthHostApi { + @async + String registerIdTokenListener( + PigeonFirebaseApp app, + ); + + @async + String registerAuthStateListener( + PigeonFirebaseApp app, + ); + + @async + void useEmulator( + PigeonFirebaseApp app, + String host, + int port, + ); + + @async + void applyActionCode( + PigeonFirebaseApp app, + String code, + ); + + @async + PigeonActionCodeInfo checkActionCode( + PigeonFirebaseApp app, + String code, + ); + + @async + void confirmPasswordReset( + PigeonFirebaseApp app, + String code, + String newPassword, + ); + + @async + PigeonUserCredential createUserWithEmailAndPassword( + PigeonFirebaseApp app, + String email, + String password, + ); + + @async + PigeonUserCredential signInAnonymously( + PigeonFirebaseApp app, + ); + + @async + PigeonUserCredential signInWithCredential( + PigeonFirebaseApp app, + Map input, + ); + + @async + PigeonUserCredential signInWithCustomToken( + PigeonFirebaseApp app, + String token, + ); + + @async + PigeonUserCredential signInWithEmailAndPassword( + PigeonFirebaseApp app, + String email, + String password, + ); + + @async + PigeonUserCredential signInWithEmailLink( + PigeonFirebaseApp app, + String email, + String emailLink, + ); + + @async + PigeonUserCredential signInWithProvider( + PigeonFirebaseApp app, + PigeonSignInProvider signInProvider, + ); + + @async + void signOut( + PigeonFirebaseApp app, + ); + + @async + List fetchSignInMethodsForEmail( + PigeonFirebaseApp app, + String email, + ); + + @async + void sendPasswordResetEmail( + PigeonFirebaseApp app, + String email, + PigeonActionCodeSettings? actionCodeSettings, + ); + + @async + void sendSignInLinkToEmail( + PigeonFirebaseApp app, + String email, + PigeonActionCodeSettings actionCodeSettings, + ); + + @async + String setLanguageCode( + PigeonFirebaseApp app, + String? languageCode, + ); + + @async + void setSettings( + PigeonFirebaseApp app, + PigeonFirebaseAuthSettings settings, + ); + + @async + String verifyPasswordResetCode( + PigeonFirebaseApp app, + String code, + ); + + @async + String verifyPhoneNumber( + PigeonFirebaseApp app, + PigeonVerifyPhoneNumberRequest request, + ); +} + +class PigeonIdTokenResult { + const PigeonIdTokenResult({ + required this.token, + required this.expirationTimestamp, + required this.authTimestamp, + required this.issuedAtTimestamp, + required this.signInProvider, + required this.claims, + required this.signInSecondFactor, + }); + + final String? token; + final int? expirationTimestamp; + final int? authTimestamp; + final int? issuedAtTimestamp; + final String? signInProvider; + final Map? claims; + final String? signInSecondFactor; +} + +class PigeonUserProfile { + const PigeonUserProfile({ + required this.displayName, + required this.photoUrl, + required this.displayNameChanged, + required this.photoUrlChanged, + }); + + final String? displayName; + final String? photoUrl; + final bool displayNameChanged; + final bool photoUrlChanged; +} + +@HostApi(dartHostTestHandler: 'TestFirebaseAuthUserHostApi') +abstract class FirebaseAuthUserHostApi { + @async + void delete( + PigeonFirebaseApp app, + ); + + @async + PigeonIdTokenResult getIdToken( + PigeonFirebaseApp app, + bool forceRefresh, + ); + + @async + PigeonUserCredential linkWithCredential( + PigeonFirebaseApp app, + Map input, + ); + + @async + PigeonUserCredential linkWithProvider( + PigeonFirebaseApp app, + PigeonSignInProvider signInProvider, + ); + + @async + PigeonUserCredential reauthenticateWithCredential( + PigeonFirebaseApp app, + Map input, + ); + + @async + PigeonUserCredential reauthenticateWithProvider( + PigeonFirebaseApp app, + PigeonSignInProvider signInProvider, + ); + + @async + PigeonUserDetails reload( + PigeonFirebaseApp app, + ); + + @async + void sendEmailVerification( + PigeonFirebaseApp app, + PigeonActionCodeSettings? actionCodeSettings, + ); + + @async + PigeonUserCredential unlink( + PigeonFirebaseApp app, + String providerId, + ); + + @async + PigeonUserDetails updateEmail( + PigeonFirebaseApp app, + String newEmail, + ); + + @async + PigeonUserDetails updatePassword( + PigeonFirebaseApp app, + String newPassword, + ); + + @async + PigeonUserDetails updatePhoneNumber( + PigeonFirebaseApp app, + Map input, + ); + + @async + PigeonUserDetails updateProfile( + PigeonFirebaseApp app, + PigeonUserProfile profile, + ); + + @async + void verifyBeforeUpdateEmail( + PigeonFirebaseApp app, + String newEmail, + PigeonActionCodeSettings? actionCodeSettings, + ); +} + @HostApi(dartHostTestHandler: 'TestMultiFactorUserHostApi') abstract class MultiFactorUserHostApi { @async void enrollPhone( - String appName, + PigeonFirebaseApp app, PigeonPhoneMultiFactorAssertion assertion, String? displayName, ); @async - PigeonMultiFactorSession getSession(String appName); + PigeonMultiFactorSession getSession( + PigeonFirebaseApp app, + ); @async void unenroll( - String appName, - String? factorUid, + PigeonFirebaseApp app, + String factorUid, ); @async - List getEnrolledFactors(String appName); + List getEnrolledFactors( + PigeonFirebaseApp app, + ); } @HostApi(dartHostTestHandler: 'TestMultiFactoResolverHostApi') abstract class MultiFactoResolverHostApi { @async - Map resolveSignIn( + PigeonUserCredential resolveSignIn( String resolverId, PigeonPhoneMultiFactorAssertion assertion, ); diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/action_code_info_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/action_code_info_test.dart index 43e3030dce5b..424a27515b21 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/action_code_info_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/action_code_info_test.dart @@ -7,13 +7,11 @@ import 'package:firebase_auth_platform_interface/firebase_auth_platform_interfac import 'package:flutter_test/flutter_test.dart'; void main() { - const int kMockOperation = 2; + const kMockOperation = ActionCodeInfoOperation.verifyEmail; const String kMockEmail = 'test@test.com'; const String kMockPreviousEmail = 'previous@test.com'; - final Map kMockData = { - 'email': kMockEmail, - 'previousEmail': kMockPreviousEmail - }; + final kMockData = + ActionCodeInfoData(email: kMockEmail, previousEmail: kMockPreviousEmail); group('$ActionCodeInfo', () { ActionCodeInfo actionCodeInfo = @@ -35,10 +33,10 @@ void main() { test('handles email is null', () { ActionCodeInfo testActionCodeInfo = ActionCodeInfo( operation: kMockOperation, - data: { - 'email': null, - 'previousEmail': kMockPreviousEmail - }); + data: ActionCodeInfoData( + email: null, + previousEmail: kMockPreviousEmail, + )); expect(testActionCodeInfo.data, isA>()); expect(testActionCodeInfo.data['email'], isNull); expect(testActionCodeInfo.data['previousEmail'], @@ -48,10 +46,10 @@ void main() { test('handles previousEmail is null', () { ActionCodeInfo testActionCodeInfo = ActionCodeInfo( operation: kMockOperation, - data: { - 'email': kMockEmail, - 'previousEmail': null - }); + data: ActionCodeInfoData( + email: kMockEmail, + previousEmail: null, + )); expect(testActionCodeInfo.data, isA>()); expect(testActionCodeInfo.data['email'], equals(kMockEmail)); expect(testActionCodeInfo.data['previousEmail'], isNull); @@ -66,8 +64,8 @@ void main() { }); test('returns operation type `emailSignIn`', () { - ActionCodeInfo testActionCodeInfo = - ActionCodeInfo(operation: 4, data: kMockData); + ActionCodeInfo testActionCodeInfo = ActionCodeInfo( + operation: ActionCodeInfoOperation.emailSignIn, data: kMockData); expect(testActionCodeInfo.operation, isA()); expect(testActionCodeInfo.operation, @@ -75,8 +73,8 @@ void main() { }); test('returns operation type `passwordReset`', () { - ActionCodeInfo testActionCodeInfo = - ActionCodeInfo(operation: 1, data: kMockData); + ActionCodeInfo testActionCodeInfo = ActionCodeInfo( + operation: ActionCodeInfoOperation.passwordReset, data: kMockData); expect(testActionCodeInfo.operation, isA()); expect(testActionCodeInfo.operation, @@ -84,8 +82,8 @@ void main() { }); test('returns operation type `recoverEmail`', () { - ActionCodeInfo testActionCodeInfo = - ActionCodeInfo(operation: 3, data: kMockData); + ActionCodeInfo testActionCodeInfo = ActionCodeInfo( + operation: ActionCodeInfoOperation.recoverEmail, data: kMockData); expect(testActionCodeInfo.operation, isA()); expect(testActionCodeInfo.operation, @@ -93,8 +91,9 @@ void main() { }); test('returns operation type `verifyAndChangeEmail`', () { - ActionCodeInfo testActionCodeInfo = - ActionCodeInfo(operation: 5, data: kMockData); + ActionCodeInfo testActionCodeInfo = ActionCodeInfo( + operation: ActionCodeInfoOperation.verifyAndChangeEmail, + data: kMockData); expect(testActionCodeInfo.operation, isA()); expect(testActionCodeInfo.operation, @@ -102,23 +101,13 @@ void main() { }); test('returns operation type `verifyEmail`', () { - ActionCodeInfo testActionCodeInfo = - ActionCodeInfo(operation: 2, data: kMockData); + ActionCodeInfo testActionCodeInfo = ActionCodeInfo( + operation: ActionCodeInfoOperation.verifyEmail, data: kMockData); expect(testActionCodeInfo.operation, isA()); expect(testActionCodeInfo.operation, equals(ActionCodeInfoOperation.verifyEmail)); }); - - test( - 'throws a [UnsupportedError] when operation does not match a known type', - () { - ActionCodeInfo testActionCodeInfo = - ActionCodeInfo(operation: -1, data: kMockData); - - expect(() => testActionCodeInfo.operation, - throwsA(isA())); - }); }); }); } diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/id_token_result_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/id_token_result_test.dart index dbfbe867ac55..72b8e69ecb11 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/id_token_result_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/id_token_result_test.dart @@ -4,6 +4,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:firebase_auth_platform_interface/src/id_token_result.dart'; +import 'package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { @@ -12,18 +13,17 @@ void main() { const int kMockExpirationTimestamp = 1234566; const int kMockAuthTimestamp = 1234567; const int kMockIssuedAtTimestamp = 12345678; - final Map kMockClaims = { + final Map kMockClaims = { 'claim1': 'value1', }; - final Map kMockData = { - 'claims': kMockClaims, - 'issuedAtTimestamp': kMockIssuedAtTimestamp, - 'authTimestamp': kMockAuthTimestamp, - 'expirationTimestamp': kMockExpirationTimestamp, - 'signInProvider': kMockSignInProvider, - 'token': kMockToken - }; + final kMockData = PigeonIdTokenResult( + claims: kMockClaims, + issuedAtTimestamp: kMockIssuedAtTimestamp, + authTimestamp: kMockAuthTimestamp, + expirationTimestamp: kMockExpirationTimestamp, + signInProvider: kMockSignInProvider, + token: kMockToken); group('$IdTokenResult', () { final idTokenResult = IdTokenResult(kMockData); @@ -48,11 +48,14 @@ void main() { }); test('returns null when data[claims] is null', () { - Map testData = { - 'claims': null, - }; + final kMockData = PigeonIdTokenResult( + issuedAtTimestamp: kMockIssuedAtTimestamp, + authTimestamp: kMockAuthTimestamp, + expirationTimestamp: kMockExpirationTimestamp, + signInProvider: kMockSignInProvider, + token: kMockToken); - final testIdTokenResult = IdTokenResult(testData); + final testIdTokenResult = IdTokenResult(kMockData); expect(testIdTokenResult.claims, isNull); }); }); diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/method_channel_firebase_auth_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/method_channel_firebase_auth_test.dart deleted file mode 100644 index f0babc0739e2..000000000000 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/method_channel_firebase_auth_test.dart +++ /dev/null @@ -1,1137 +0,0 @@ -// ignore_for_file: require_trailing_commas -// Copyright 2020, the Chromium project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:async'; -import 'dart:io'; - -import 'package:firebase_auth_platform_interface/firebase_auth_platform_interface.dart'; -import 'package:firebase_auth_platform_interface/src/method_channel/method_channel_firebase_auth.dart'; -import 'package:firebase_auth_platform_interface/src/method_channel/method_channel_multi_factor.dart'; -import 'package:firebase_auth_platform_interface/src/method_channel/method_channel_user.dart'; -import 'package:firebase_core/firebase_core.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import '../mock.dart'; - -void main() { - setupFirebaseAuthMocks(); - - late MultiFactorPlatform multiFactor; - - late FirebaseAuthPlatform auth; - final List log = []; - const String regularTestEmail = 'test@email.com'; - const String testPassword = 'testPassword'; - - // mock props - bool mockPlatformExceptionThrown = false; - bool mockExceptionThrown = false; - const String kMockUid = '12345'; - const String kMockProviderId = 'firebase'; - const String kMockDisplayName = 'Flutter Test User'; - const String kMockEmail = 'test@example.com'; - const String kMockPhotoURL = 'http://www.example.com/'; - final int kMockCreationTimestamp = - DateTime.now().subtract(const Duration(days: 2)).millisecondsSinceEpoch; - final int kMockLastSignInTimestamp = - DateTime.now().subtract(const Duration(days: 1)).millisecondsSinceEpoch; - Map kMockUser = { - 'uid': kMockUid, - 'isAnonymous': false, - 'emailVerified': false, - 'metadata': { - 'creationTime': kMockCreationTimestamp, - 'lastSignInTime': kMockLastSignInTimestamp, - }, - 'photoURL': kMockPhotoURL, - 'providerData': >[ - { - 'providerId': kMockProviderId, - 'uid': kMockUid, - 'displayName': kMockDisplayName, - 'photoURL': kMockPhotoURL, - 'email': kMockEmail, - }, - ], - }; - - final Map kMockInitialProviders = { - 'providers': ['facebook'] - }; - - const Map kMockActionCodeInfoData = { - 'email': regularTestEmail, - 'previousEmail': 'previous@email.com' - }; - - final ActionCodeInfo kMockActionCodeInfo = ActionCodeInfo( - operation: 1, - data: kMockActionCodeInfoData, - ); - - const Map kMockAdditionalUserInfo = { - 'isNewUser': false, - 'username': 'flutterUser', - 'providerId': 'testProvider', - 'profile': {'foo': 'bar'}, - }; - - Future mockSignIn() async { - await auth.signInAnonymously(); - } - - void verifyUser(UserPlatform user) { - expect(user, isA()); - expect(user.uid, isA()); - expect(user.email, equals(regularTestEmail)); - expect(user.isAnonymous, isFalse); - expect(user.uid, equals(auth.currentUser!.uid)); - } - - void verifyUserCredential(UserCredentialPlatform result) { - verifyUser(result.user!); - var additionalUserInfo = result.additionalUserInfo!; - expect(additionalUserInfo, isA()); - expect(additionalUserInfo.isNewUser, isFalse); - } - - group('$MethodChannelFirebaseAuth', () { - late Map user; - - setUpAll(() async { - FirebaseApp app = await Firebase.initializeApp(); - - handleMethodCall((call) async { - log.add(call); - - if (mockExceptionThrown) { - throw Exception(); - } else if (mockPlatformExceptionThrown) { - throw PlatformException(code: 'UNKNOWN'); - } - - switch (call.method) { - case 'Auth#registerIdTokenListener': - const String name = 'idTokenChannel'; - handleEventChannel(name, log); - return name; - case 'Auth#registerAuthStateListener': - const String name = 'authStateChannel'; - handleEventChannel(name, log); - return name; - case 'Auth#signInAnonymously': - user = generateUser(user, { - 'isAnonymous': true, - }); - return {'user': user}; - case 'Auth#signInWithEmailLink': - case 'Auth#signInWithEmailAndPassword': - user = generateUser( - user, {'email': call.arguments['email']}); - return { - 'user': user, - 'additionalUserInfo': kMockAdditionalUserInfo - }; - case 'Auth#signInWithCustomToken': - user = generateUser(user, { - 'email': regularTestEmail, - }); - return { - 'user': user, - 'additionalUserInfo': kMockAdditionalUserInfo - }; - case 'Auth#signInWithCredential': - user = generateUser(user, { - 'email': call.arguments['credential']['email'], - }); - return { - 'user': user, - 'additionalUserInfo': kMockAdditionalUserInfo - }; - case 'Auth#verifyPasswordResetCode': - return {'email': call.arguments['code']}; - case 'Auth#verifyPhoneNumber': - const String name = 'phoneNumberVerifier'; - handleEventChannel(name, log); - return name; - case 'Auth#checkActionCode': - return { - 'operation': 2, - 'data': kMockActionCodeInfoData, - }; - case 'Auth#setLanguageCode': - return { - 'languageCode': call.arguments['languageCode'] - }; - case 'Auth#setSettings': - return null; - case 'Auth#fetchSignInMethodsForEmail': - return kMockInitialProviders; - - default: - return {'user': kMockUser}; - } - }); - - auth = MethodChannelFirebaseAuth.instance.delegateFor(app: app); - // TODO(Lyokone): mock properly - multiFactor = MethodChannelMultiFactor(auth); - - user = kMockUser; - }); - - setUp(() async { - user = kMockUser; - log.clear(); - }); - - tearDown(() async { - mockPlatformExceptionThrown = false; - mockExceptionThrown = false; - await auth.signOut(); - }); - - test('currentUser', () async { - await mockSignIn(); - expect(auth.currentUser, isA()); - }); - - test('setCurrentUser()', () async { - expect(auth.currentUser, isNull); - MockUserPlatform userPlatform = MockUserPlatform(auth, multiFactor, user); - auth.currentUser = userPlatform; - expect(auth.currentUser, isA()); - expect(auth.currentUser!.uid, equals(kMockUid)); - }); - - test('delegateFor()', () { - final testAuth = TestMethodChannelFirebaseAuth(Firebase.app()); - final result = testAuth.delegateFor(app: Firebase.app()); - - expect(result, isA()); - expect(result.app, isA()); - }); - - group('setInitialValues()', () { - test('when currentUser arg is not null', () { - final testAuth = TestMethodChannelFirebaseAuth(Firebase.app()); - final result = testAuth.setInitialValues( - currentUser: kMockUser, languageCode: 'en'); - expect(result, isA()); - expect(result.languageCode, equals('en')); - expect(result.currentUser, isA()); - expect(testAuth.currentUser, isA()); - }); - - test('when currentUser arg is null', () { - final testAuth = TestMethodChannelFirebaseAuth(Firebase.app()); - final result = testAuth.setInitialValues(languageCode: 'en'); - expect(result, isA()); - expect(result.languageCode, equals('en')); - expect(result.currentUser, isNull); - expect(testAuth.currentUser, isNull); - }); - }); - - group('applyActionCode()', () { - const String code = '12345'; - test('invokes native method with correct args', () async { - await auth.applyActionCode(code); - - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#applyActionCode', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'code': code, - }, - ), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - void callMethod() => auth.applyActionCode(code); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - void callMethod() => auth.applyActionCode(code); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('checkActionCode()', () { - const String code = '12345'; - - test('invokes native method with correct args and returns correct result', - () async { - final result = await auth.checkActionCode(code); - - // check result - expect(result, isA()); - expect(result.operation, equals(ActionCodeInfoOperation.verifyEmail)); - expect(result.data, isA>()); - expect(result.data['email'], equals(kMockActionCodeInfo.data['email'])); - expect( - result.data['previousEmail'], - equals(kMockActionCodeInfo.data['previousEmail']), - ); - - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#checkActionCode', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'code': code, - }, - ), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - void callMethod() => auth.checkActionCode(code); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - void callMethod() => auth.checkActionCode(code); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('confirmPasswordReset()', () { - const String code = '12345'; - const String newPassword = 'newPassword'; - test('invokes native method with correct args', () async { - await auth.confirmPasswordReset(code, newPassword); - - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#confirmPasswordReset', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'code': code, - 'newPassword': newPassword, - }, - ), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - void callMethod() => auth.confirmPasswordReset(code, newPassword); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - void callMethod() => auth.confirmPasswordReset(code, newPassword); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('createUserWithEmailAndPassword()', () { - test('invokes native method with correct args', () async { - await auth.createUserWithEmailAndPassword( - regularTestEmail, testPassword); - - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#createUserWithEmailAndPassword', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'email': regularTestEmail, - 'password': testPassword, - }, - ), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - void callMethod() => - auth.createUserWithEmailAndPassword(regularTestEmail, testPassword); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - void callMethod() => - auth.createUserWithEmailAndPassword(regularTestEmail, testPassword); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('fetchSignInMethodsForEmail()', () { - test('invokes native method with correct args', () async { - await auth.fetchSignInMethodsForEmail(regularTestEmail); - - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#fetchSignInMethodsForEmail', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'email': regularTestEmail, - }, - ), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - void callMethod() => auth.fetchSignInMethodsForEmail(regularTestEmail); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - void callMethod() => auth.fetchSignInMethodsForEmail(regularTestEmail); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('signInAnonymously()', () { - test('returns result of a successful sign in', () async { - final result = await auth.signInAnonymously(); - - // check result - expect(result, isA()); - expect(result.user, isA()); - - final userResult = result.user!; - expect(userResult.uid, isA()); - expect(userResult.email, isNull); - expect(userResult.isAnonymous, isTrue); - expect(userResult.uid, equals(auth.currentUser!.uid)); - - final additionalUserInfo = result.additionalUserInfo; - expect(additionalUserInfo, isNull); - - // check currentUser was set - expect(auth.currentUser, isA()); - expect(auth.currentUser!.isAnonymous, isTrue); - - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#signInAnonymously', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - }, - ), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => auth.signInAnonymously(); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - - void callMethod() => auth.signInAnonymously(); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('signInWithCredential()', () { - test('returns result of a successful sign in', () async { - final credential = EmailAuthProvider.credential( - email: regularTestEmail, password: testPassword); - final result = await auth.signInWithCredential(credential); - - // check result - expect(result, isA()); - verifyUserCredential(result); - - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#signInWithCredential', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'credential': credential.asMap() - }, - ), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - final credential = EmailAuthProvider.credential( - email: 'disabled@account.com', password: testPassword); - - void callMethod() => auth.signInWithCredential(credential); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - final credential = EmailAuthProvider.credential( - email: 'unknown', password: testPassword); - - void callMethod() => auth.signInWithCredential(credential); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('signInWithCustomToken()', () { - test('returns result of a successful sign in', () async { - const String token = 'testToken'; - final result = await auth.signInWithCustomToken(token); - - // check result - expect(result, isA()); - verifyUserCredential(result); - - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#signInWithCustomToken', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'token': token - }, - ), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - const String token = 'testToken'; - void callMethod() => auth.signInWithCustomToken(token); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - const String token = 'testToken'; - void callMethod() => auth.signInWithCustomToken(token); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('signInWithEmailAndPassword()', () { - test('returns result of a successful sign in', () async { - final result = await auth.signInWithEmailAndPassword( - regularTestEmail, testPassword); - - // check result - expect(result, isA()); - verifyUserCredential(result); - - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#signInWithEmailAndPassword', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'email': regularTestEmail, - 'password': testPassword - }, - ), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => - auth.signInWithEmailAndPassword(regularTestEmail, testPassword); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - - void callMethod() => - auth.signInWithEmailAndPassword(regularTestEmail, testPassword); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('signInWithEmailLink()', () { - test('returns result of a successful sign in', () async { - const String emailLink = 'testEmailLink'; - final result = - await auth.signInWithEmailLink(regularTestEmail, emailLink); - - // check result - expect(result, isA()); - verifyUserCredential(result); - - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#signInWithEmailLink', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'email': regularTestEmail, - 'emailLink': emailLink - }, - ), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - void callMethod() => - auth.signInWithEmailAndPassword(regularTestEmail, testPassword); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - void callMethod() => - auth.signInWithEmailAndPassword(regularTestEmail, testPassword); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('sendPasswordResetEmail()', () { - final ActionCodeSettings actionCodeSettings = - ActionCodeSettings(url: 'test'); - test('invokes native method with correct args', () async { - await auth.sendPasswordResetEmail(regularTestEmail, actionCodeSettings); - - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#sendPasswordResetEmail', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'email': regularTestEmail, - 'actionCodeSettings': actionCodeSettings.asMap(), - }, - ), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - void callMethod() => - auth.sendPasswordResetEmail(regularTestEmail, actionCodeSettings); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - void callMethod() => - auth.sendPasswordResetEmail(regularTestEmail, actionCodeSettings); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('sendSignInLinkToEmail()', () { - final ActionCodeSettings actionCodeSettings = - ActionCodeSettings(url: 'test'); - - test('invokes native method with correct args', () async { - await auth.sendSignInLinkToEmail(regularTestEmail, actionCodeSettings); - - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#sendSignInLinkToEmail', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'email': regularTestEmail, - 'actionCodeSettings': actionCodeSettings.asMap(), - }, - ), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - void callMethod() => - auth.sendSignInLinkToEmail(regularTestEmail, actionCodeSettings); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - void callMethod() => - auth.sendPasswordResetEmail(regularTestEmail, actionCodeSettings); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('setLanguageCode()', () { - const String languageCode = 'en'; - test('invokes native method with correct args', () async { - await auth.setLanguageCode(languageCode); - - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#setLanguageCode', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'languageCode': languageCode, - }, - ), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - void callMethod() => auth.setLanguageCode(languageCode); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - void callMethod() => auth.setLanguageCode(languageCode); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('setSettings()', () { - const bool isDisabled = true; - test('invokes native method with correct args', () async { - String groupId = 'group-id'; - String phoneNumber = '555-5555'; - String smsCode = '123456'; - bool forceRecaptchaFlow = true; - - await auth.setSettings( - appVerificationDisabledForTesting: isDisabled, - userAccessGroup: groupId, - phoneNumber: phoneNumber, - smsCode: smsCode, - forceRecaptchaFlow: forceRecaptchaFlow, - ); - - if (Platform.isIOS || Platform.isMacOS) { - expect(log, [ - isMethodCall( - 'Auth#setSettings', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'appVerificationDisabledForTesting': isDisabled, - 'userAccessGroup': groupId, - }, - ), - ]); - } - if (Platform.isAndroid) { - expect(log, [ - isMethodCall( - 'Auth#setSettings', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'appVerificationDisabledForTesting': isDisabled, - 'phoneNumber': phoneNumber, - 'smsCode': smsCode, - 'forceRecaptchaFlow': forceRecaptchaFlow, - }, - ), - ]); - } - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - void callMethod() => - auth.setSettings(appVerificationDisabledForTesting: isDisabled); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - void callMethod() => - auth.setSettings(appVerificationDisabledForTesting: isDisabled); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('setPersistence()', () { - test('throw [UnimplementedError]', () async { - const Persistence persistence = Persistence.LOCAL; - try { - await auth.setPersistence(persistence); - } on UnimplementedError catch (e) { - expect( - e.message, - equals( - 'setPersistence() is only supported on web based platforms')); - } catch (e) { - fail('should have thrown an UnimplementedError'); - } - }); - }); - - group('signInWithPopup()', () { - test('throw [UnimplementedError]', () async { - final FacebookAuthProvider facebookProvider = FacebookAuthProvider(); - try { - await auth.signInWithPopup(facebookProvider); - } on UnimplementedError catch (e) { - expect( - e.message, - equals( - 'signInWithPopup() is only supported on web based platforms')); - } catch (e) { - fail('should have thrown an UnimplementedError'); - } - }); - }); - - group('signInWithRedirect()', () { - test('throw [UnimplementedError]', () async { - final FacebookAuthProvider facebookProvider = FacebookAuthProvider(); - try { - await auth.signInWithRedirect(facebookProvider); - } on UnimplementedError catch (e) { - expect( - e.message, - equals( - 'signInWithRedirect() is only supported on web based platforms')); - } catch (e) { - fail('should have thrown an UnimplementedError'); - } - }); - }); - - group('signOut()', () { - test('logs user out correctly', () async { - await auth.signOut(); - - expect(auth.currentUser, isNull); - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#signOut', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - }, - ), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => auth.signOut(); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - - void callMethod() => auth.signOut(); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('useEmulator()', () { - test('calls useEmulator correctly', () async { - await auth.useAuthEmulator('example.com', 31337); - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#useEmulator', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'host': 'example.com', - 'port': 31337, - }, - ), - ]); - }); - }); - - group('verifyPasswordResetCode()', () { - const String testCode = 'testCode'; - test('returns a successful result', () async { - final result = await auth.verifyPasswordResetCode(testCode); - - expect(result, isA()); - expect(result, equals(testCode)); - - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#verifyPasswordResetCode', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'code': testCode, - }, - ), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - void callMethod() => auth.verifyPasswordResetCode(testCode); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - - void callMethod() => auth.verifyPasswordResetCode(testCode); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('verifyPhoneNumber()', () { - const String testPhoneNumber = '+1 555 555 555'; - const String testSmsCode = '12345'; - const Duration testTimeout = Duration(seconds: 5); - - test('returns a successful result', () async { - await auth.verifyPhoneNumber( - phoneNumber: testPhoneNumber, - verificationCompleted: (PhoneAuthCredential phoneAuthCredential) {}, - verificationFailed: (_) {}, - codeSent: (_, __) {}, - codeAutoRetrievalTimeout: (_) {}, - timeout: testTimeout, - autoRetrievedSmsCodeForTesting: testSmsCode, - ); - - // check native method was called - expect(log, [ - isMethodCall( - 'Auth#verifyPhoneNumber', - arguments: { - 'appName': defaultFirebaseAppName, - 'tenantId': null, - 'phoneNumber': testPhoneNumber, - 'timeout': testTimeout.inMilliseconds, - 'forceResendingToken': null, - 'autoRetrievedSmsCodeForTesting': testSmsCode, - }, - ), - isMethodCall('listen', arguments: null), - ]); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - void callMethod() => auth.verifyPhoneNumber( - phoneNumber: testPhoneNumber, - verificationCompleted: (_) {}, - verificationFailed: (_) {}, - codeSent: (_, __) {}, - codeAutoRetrievalTimeout: (_) {}, - timeout: testTimeout, - autoRetrievedSmsCodeForTesting: testSmsCode, - ); - await testExceptionHandling('PLATFORM', callMethod); - }); - - test('throws an [Exception] error', () async { - mockExceptionThrown = true; - void callMethod() => auth.verifyPhoneNumber( - phoneNumber: testPhoneNumber, - verificationCompleted: (_) {}, - verificationFailed: (_) {}, - codeSent: (_, __) {}, - codeAutoRetrievalTimeout: (_) {}, - timeout: testTimeout, - autoRetrievedSmsCodeForTesting: testSmsCode, - ); - await testExceptionHandling('EXCEPTION', callMethod); - }); - }); - - group('authStateChanges()', () { - test('returns [Stream]', () async { - // Checks that `authStateChanges` does not throw UnimplementedError - expect(auth.authStateChanges(), isNotNull); - }); - - test('listens to incoming changes', () async { - Stream stream = - auth.authStateChanges().asBroadcastStream(); - - await expectLater(stream, emits(isNull)); - expect(auth.currentUser, equals(isNull)); - - await injectEventChannelResponse('authStateChannel', {'user': user}); - - await expectLater( - stream, - emits(isA().having((e) => e.uid, 'uid', kMockUid)), - ); - expect(auth.currentUser!.uid, equals(kMockUid)); - - expect(log, isEmpty); - }); - - test('emits the latest user available', () async { - Stream stream = auth.authStateChanges(); - - await injectEventChannelResponse('authStateChannel', {'user': user}); - - await expectLater( - stream, - emits(isA().having((e) => e.uid, 'uid', kMockUid)), - ); - - expect(auth.currentUser!.uid, equals(kMockUid)); - expect(log, isEmpty); - }); - }); - - group('idTokenChanges()', () { - test('returns [Stream]', () async { - // Checks that `idTokenChanges` does not throw UnimplementedError - expect(auth.idTokenChanges(), isNotNull); - }); - - test('listens to incoming changes', () async { - Stream stream = - auth.idTokenChanges().asBroadcastStream(); - - await expectLater(stream, emits(isNull)); - expect(auth.currentUser, equals(isNull)); - - await injectEventChannelResponse('idTokenChannel', {'user': user}); - - await expectLater( - stream, - emits(isA().having((e) => e.uid, 'uid', kMockUid)), - ); - expect(auth.currentUser!.uid, equals(kMockUid)); - - expect(log, isEmpty); - }); - - test('emits the latest user available', () async { - Stream stream = auth.idTokenChanges(); - - await injectEventChannelResponse('idTokenChannel', {'user': null}); - await injectEventChannelResponse('idTokenChannel', {'user': user}); - - await expectLater( - stream, - emits(isA().having((e) => e.uid, 'uid', kMockUid)), - ); - - expect(auth.currentUser!.uid, equals(kMockUid)); - expect(log, isEmpty); - }); - }); - - group('userChanges()', () { - test('returns [Stream]', () async { - // Checks that `userChanges` does not throw UnimplementedError - expect(auth.userChanges(), isNotNull); - }); - - test('listens to incoming changes', () async { - Stream stream = auth.userChanges().asBroadcastStream(); - - await expectLater(stream, emits(isNull)); - expect(auth.currentUser, equals(isNull)); - - await injectEventChannelResponse('idTokenChannel', {'user': user}); - - await expectLater( - stream, - emits(isA().having((e) => e.uid, 'uid', kMockUid)), - ); - expect(auth.currentUser!.uid, equals(kMockUid)); - - expect(log, isEmpty); - }); - - test('emits the latest user available', () async { - Stream stream = auth.userChanges(); - // id token change events will trigger setCurrentUser() - // and hence userChange events - await injectEventChannelResponse('idTokenChannel', {'user': null}); - await injectEventChannelResponse('idTokenChannel', {'user': user}); - - await expectLater( - stream, - emits(isA().having((e) => e.uid, 'uid', kMockUid)), - ); - - expect(auth.currentUser!.uid, equals(kMockUid)); - expect(log, isEmpty); - }); - }); - }); -} - -class MockUserPlatform extends UserPlatform { - MockUserPlatform(FirebaseAuthPlatform auth, MultiFactorPlatform multiFactor, - Map user) - : super(auth, multiFactor, user); -} - -class TestMethodChannelFirebaseAuth extends MethodChannelFirebaseAuth { - TestMethodChannelFirebaseAuth(FirebaseApp app) : super(app: app); -} diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/method_channel_user_credential_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/method_channel_user_credential_test.dart index 8cb84455a85f..d35bcefe3bba 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/method_channel_user_credential_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/method_channel_user_credential_test.dart @@ -6,6 +6,7 @@ import 'package:firebase_auth_platform_interface/firebase_auth_platform_interface.dart'; import 'package:firebase_auth_platform_interface/src/method_channel/method_channel_user.dart'; import 'package:firebase_auth_platform_interface/src/method_channel/method_channel_user_credential.dart'; +import 'package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -21,26 +22,30 @@ void main() { const String kMockProviderId = 'provider-id'; const String kMockSignInMethod = 'password'; - final Map kMockInitialUserData = { - 'user': { - 'uid': kMockUid, - 'email': kMockEmail, - }, - 'additionalUserInfo': { - 'profile': {'foo': 'bar'}, - 'isNewUser': true, - 'providerId': 'info$kMockProviderId', - 'username': 'info$kMockUsername', - }, - 'authCredential': { - 'providerId': 'auth$kMockProviderId', - 'signInMethod': kMockSignInMethod, - }, - }; - group('$MethodChannelUserCredential()', () { late MethodChannelUserCredential userCredential; - late Map userData = kMockInitialUserData; + PigeonUserCredential userData = PigeonUserCredential( + user: PigeonUserDetails( + userInfo: PigeonUserInfo( + uid: kMockUid, + email: kMockEmail, + isAnonymous: false, + isEmailVerified: false, + ), + providerData: [], + ), + additionalUserInfo: PigeonAdditionalUserInfo( + isNewUser: true, + profile: {'foo': 'bar'}, + providerId: 'info$kMockProviderId', + username: 'info$kMockUsername', + ), + credential: PigeonAuthCredential( + providerId: 'auth$kMockProviderId', + signInMethod: kMockSignInMethod, + nativeId: 0, + ), + ); setUpAll(() async { await Firebase.initializeApp(); @@ -50,7 +55,30 @@ void main() { }); setUp(() { - userData = Map.from(kMockInitialUserData); + final kMockInitialUserData = PigeonUserCredential( + user: PigeonUserDetails( + userInfo: PigeonUserInfo( + uid: kMockUid, + email: kMockEmail, + isAnonymous: false, + isEmailVerified: false, + ), + providerData: [], + ), + additionalUserInfo: PigeonAdditionalUserInfo( + isNewUser: true, + profile: {'foo': 'bar'}, + providerId: 'info$kMockProviderId', + username: 'info$kMockUsername', + ), + credential: PigeonAuthCredential( + providerId: 'auth$kMockProviderId', + signInMethod: kMockSignInMethod, + nativeId: 0, + ), + ); + + userData = kMockInitialUserData; }); group('Constructor', () { @@ -84,7 +112,7 @@ void main() { }); test('set additionalUserInfo to null', () { - userData['additionalUserInfo'] = null; + userData.additionalUserInfo = null; MethodChannelUserCredential testUser = MethodChannelUserCredential(auth, userData); @@ -92,7 +120,7 @@ void main() { }); test('set additionalUserInfo.profile to empty map', () { - userData['additionalUserInfo']['profile'] = null; + userData.additionalUserInfo?.profile = null; MethodChannelUserCredential testUser = MethodChannelUserCredential(auth, userData); @@ -103,7 +131,7 @@ void main() { }); test('set authCredential to null', () { - userData['authCredential'] = null; + userData.credential = null; MethodChannelUserCredential testUser = MethodChannelUserCredential(auth, userData); @@ -111,7 +139,7 @@ void main() { }); test('set user to null', () { - userData['user'] = null; + userData.user = null; MethodChannelUserCredential testUser = MethodChannelUserCredential(auth, userData); diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/method_channel_user_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/method_channel_user_test.dart deleted file mode 100644 index 146a834c802b..000000000000 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/method_channel_user_test.dart +++ /dev/null @@ -1,737 +0,0 @@ -// ignore_for_file: require_trailing_commas -// Copyright 2020, the Chromium project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'package:firebase_auth_platform_interface/firebase_auth_platform_interface.dart'; -import 'package:firebase_auth_platform_interface/src/method_channel/method_channel_user.dart'; -import 'package:firebase_core/firebase_core.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:firebase_auth_platform_interface/src/method_channel/method_channel_firebase_auth.dart'; -import '../mock.dart'; -import 'package:flutter/services.dart'; - -void main() { - setupFirebaseAuthMocks(); - - final List log = []; - bool mockPlatformExceptionThrown = false; - bool mockExceptionThrown = false; - late FirebaseAuthPlatform auth; - const String kMockProviderId = 'firebase'; - const String kMockUid = '12345'; - const String kMockDisplayName = 'Flutter Test User'; - const String kMockPhotoURL = 'http://www.example.com/'; - const String kMockEmail = 'test@example.com'; - const String kMockIdToken = '12345'; - const String kMockNewPhoneNumber = '5555555556'; - const String kMockIdTokenResultSignInProvider = 'password'; - const String kMockIdTokenResultSignInFactor = 'test'; - const Map kMockIdTokenResultClaims = { - 'claim1': 'value1', - }; - const String kMockPhoneNumber = TEST_PHONE_NUMBER; - final int kMockIdTokenResultExpirationTimestamp = - DateTime.now().subtract(const Duration(days: 1)).millisecondsSinceEpoch; - final int kMockIdTokenResultAuthTimestamp = - DateTime.now().subtract(const Duration(days: 1)).millisecondsSinceEpoch; - final int kMockIdTokenResultIssuedAtTimestamp = - DateTime.now().subtract(const Duration(days: 1)).millisecondsSinceEpoch; - final Map kMockIdTokenResult = { - 'token': kMockIdToken, - 'expirationTimestamp': kMockIdTokenResultExpirationTimestamp, - 'authTimestamp': kMockIdTokenResultAuthTimestamp, - 'issuedAtTimestamp': kMockIdTokenResultIssuedAtTimestamp, - 'signInProvider': kMockIdTokenResultSignInProvider, - 'claims': kMockIdTokenResultClaims, - 'signInSecondFactor': kMockIdTokenResultSignInFactor - }; - - final int kMockCreationTimestamp = - DateTime.now().subtract(const Duration(days: 2)).millisecondsSinceEpoch; - final int kMockLastSignInTimestamp = - DateTime.now().subtract(const Duration(days: 1)).millisecondsSinceEpoch; - - final List kMockInitialProviderData = [ - { - 'providerId': kMockProviderId, - 'uid': kMockUid, - 'displayName': kMockDisplayName, - 'photoURL': kMockPhotoURL, - 'email': kMockEmail, - 'phoneNumber': kMockPhoneNumber, - }, - ]; - - Map kMockUser = { - 'uid': kMockUid, - 'isAnonymous': true, - 'emailVerified': false, - 'metadata': { - 'creationTime': kMockCreationTimestamp, - 'lastSignInTime': kMockLastSignInTimestamp, - }, - 'photoURL': kMockPhotoURL, - 'providerData': kMockInitialProviderData, - }; - - Future mockSignIn() async { - await auth.signInAnonymously(); - } - - group('$MethodChannelUser', () { - late Map user; - late List kMockProviderData; - - setUpAll(() async { - FirebaseApp app = await Firebase.initializeApp(); - - handleMethodCall((call) async { - log.add(call); - - if (mockExceptionThrown) { - throw Exception(); - } else if (mockPlatformExceptionThrown) { - throw PlatformException(code: 'UNKNOWN'); - } - - switch (call.method) { - case 'Auth#registerIdTokenListener': - const String name = 'idTokenChannel'; - handleEventChannel(name, log); - return name; - case 'Auth#registerAuthStateListener': - const String name = 'authStateChannel'; - handleEventChannel(name, log); - return name; - case 'Auth#signInAnonymously': - return {'user': user}; - case 'Auth#signInWithEmailAndPassword': - user = generateUser( - user, {'email': call.arguments['email']}); - return {'user': user}; - case 'User#updateProfile': - Map previousUser = user; - user = generateUser( - user, Map.from(call.arguments['profile'])); - return previousUser; - case 'User#updatePhoneNumber': - Map previousUser = user; - user = generateUser( - user, {'phoneNumber': kMockNewPhoneNumber}); - return previousUser; - case 'User#updatePassword': - case 'User#updateEmail': - case 'User#sendLinkToEmail': - case 'User#sendPasswordResetEmail': - Map previousUser = user; - user = generateUser( - user, {'email': call.arguments['newEmail']}); - return previousUser; - case 'User#getIdToken': - if (call.arguments['tokenOnly'] == false) { - return kMockIdTokenResult; - } - return {'token': kMockIdToken}; - case 'User#reload': - return user; - case 'User#reauthenticateUserWithCredential': - case 'User#linkWithCredential': - user = generateUser( - user, {'providerData': kMockProviderData}); - return {'user': user}; - case 'User#unlink': - user = generateUser(user, {'providerData': []}); - return {'user': user}; - default: - return {'user': user}; - } - }); - - auth = MethodChannelFirebaseAuth(app: app); - user = kMockUser; - }); - - setUp(() async { - user = kMockUser; - - mockPlatformExceptionThrown = false; - mockExceptionThrown = false; - kMockProviderData = List.from(kMockInitialProviderData); - await mockSignIn(); - - log.clear(); - }); - group('User.displayName', () { - test('should return null', () async { - expect(auth.currentUser!.displayName, isNull); - }); - test('should return correct value', () async { - // Setup - user = - generateUser(user, {'displayName': 'updatedName'}); - await auth.currentUser!.reload(); - - expect(auth.currentUser!.displayName, equals('updatedName')); - }); - }); - - group('User.email', () { - test('should return null', () async { - expect(auth.currentUser!.email, isNull); - }); - test('should return correct value', () async { - const updatedEmail = 'updated@email.com'; - user = generateUser(user, {'email': updatedEmail}); - await auth.currentUser!.reload(); - - expect(auth.currentUser!.email, equals(updatedEmail)); - }); - }); - - group('User.emailVerified', () { - test('should return false', () async { - expect(auth.currentUser!.emailVerified, isFalse); - }); - test('should return true', () async { - user = generateUser(user, {'emailVerified': true}); - await auth.currentUser!.reload(); - - expect(auth.currentUser!.emailVerified, isTrue); - }); - }); - - group('User.isAnonymous', () { - test('should return true', () async { - expect(auth.currentUser!.isAnonymous, isTrue); - }); - test('should return false', () async { - user = generateUser(user, {'isAnonymous': false}); - await auth.currentUser!.reload(); - - expect(auth.currentUser!.isAnonymous, isFalse); - }); - }); - - test('User.metadata', () async { - final metadata = auth.currentUser!.metadata; - - expect(metadata, isA()); - expect(metadata.creationTime!.millisecondsSinceEpoch, - kMockCreationTimestamp); - expect(metadata.lastSignInTime!.millisecondsSinceEpoch, - kMockLastSignInTimestamp); - }); - - test('User.photoURL', () async { - expect(auth.currentUser!.photoURL, equals(kMockPhotoURL)); - }); - - test('User.providerData', () async { - final providerData = auth.currentUser!.providerData; - expect(providerData, isA>()); - - expect(providerData[0].displayName, equals(kMockDisplayName)); - expect(providerData[0].email, equals(kMockEmail)); - expect(providerData[0].photoURL, equals(kMockPhotoURL)); - expect(providerData[0].phoneNumber, equals(kMockPhoneNumber)); - expect(providerData[0].uid, equals(kMockUid)); - expect(providerData[0].providerId, equals(kMockProviderId)); - }); - - test('User.refreshToken', () async { - expect(auth.currentUser!.refreshToken, isNull); - }); - - test('User.tenantId', () async { - expect(auth.currentUser!.tenantId, isNull); - }); - - test('User.uid', () async { - expect(auth.currentUser!.uid, equals(kMockUid)); - }); - - group('delete()', () { - test('should run successfully', () async { - await auth.currentUser!.delete(); - - expect( - log, - [ - isMethodCall( - 'User#delete', - arguments: { - 'appName': '[DEFAULT]', - 'tenantId': null - }, - ), - ], - ); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => auth.currentUser!.delete(); - await testExceptionHandling('PLATFORM', callMethod); - }); - }); - - group('getIdToken()', () { - test('should run successfully', () async { - final token = await auth.currentUser!.getIdToken(true); - - expect( - log, - [ - isMethodCall( - 'User#getIdToken', - arguments: { - 'appName': '[DEFAULT]', - 'tenantId': null, - 'forceRefresh': true, - 'tokenOnly': true - }, - ), - ], - ); - expect(token, isA()); - expect(token, equals(kMockIdToken)); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => auth.currentUser!.getIdToken(true); - await testExceptionHandling('PLATFORM', callMethod); - }); - }); - group('getIdTokenResult()', () { - test('should run successfully', () async { - final idTokenResult = await auth.currentUser!.getIdTokenResult(true); - - expect( - log, - [ - isMethodCall( - 'User#getIdToken', - arguments: { - 'appName': '[DEFAULT]', - 'tenantId': null, - 'forceRefresh': true, - 'tokenOnly': false - }, - ), - ], - ); - expect(idTokenResult, isA()); - expect(idTokenResult.authTime!.millisecondsSinceEpoch, - equals(kMockIdTokenResultAuthTimestamp)); - expect(idTokenResult.claims, equals(kMockIdTokenResultClaims)); - expect(idTokenResult.expirationTime!.millisecondsSinceEpoch, - equals(kMockIdTokenResultExpirationTimestamp)); - expect(idTokenResult.issuedAtTime!.millisecondsSinceEpoch, - equals(kMockIdTokenResultIssuedAtTimestamp)); - expect(idTokenResult.token, equals(kMockIdToken)); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => auth.currentUser!.getIdTokenResult(true); - await testExceptionHandling('PLATFORM', callMethod); - }); - }); - - group('linkWithCredential()', () { - String newEmail = 'new@email.com'; - EmailAuthCredential credential = - EmailAuthProvider.credential(email: newEmail, password: 'test') - as EmailAuthCredential; - - test('should run successfully', () async { - kMockProviderData.add({ - 'email': newEmail, - 'providerId': 'email', - 'uid': kMockUid, - 'displayName': kMockDisplayName, - 'photoURL': kMockPhotoURL, - }); - final result = await auth.currentUser!.linkWithCredential(credential); - - expect( - log, - [ - isMethodCall( - 'User#linkWithCredential', - arguments: { - 'appName': '[DEFAULT]', - 'tenantId': null, - 'credential': credential.asMap() - }, - ), - ], - ); - expect(result, isA()); - expect(result.user!.providerData.length, equals(2)); - - // check currentUser updated - expect(auth.currentUser!.providerData.length, equals(2)); - expect(auth.currentUser!.providerData[1].email, equals(newEmail)); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => auth.currentUser!.linkWithCredential(credential); - await testExceptionHandling('PLATFORM', callMethod); - }); - }); - - group('reauthenticateWithCredential()', () { - String newEmail = 'new@email.com'; - EmailAuthCredential credential = - EmailAuthProvider.credential(email: newEmail, password: 'test') - as EmailAuthCredential; - - test('should run successfully', () async { - kMockProviderData.add({ - 'email': newEmail, - 'providerId': 'email', - 'uid': kMockUid, - 'displayName': kMockDisplayName, - 'photoURL': kMockPhotoURL, - }); - final result = - await auth.currentUser!.reauthenticateWithCredential(credential); - - expect( - log, - [ - isMethodCall( - 'User#reauthenticateUserWithCredential', - arguments: { - 'appName': '[DEFAULT]', - 'tenantId': null, - 'credential': credential.asMap() - }, - ), - ], - ); - expect(result, isA()); - expect(result.user!.providerData.length, equals(2)); - - // check currentUser updated - expect(auth.currentUser!.providerData.length, equals(2)); - expect(auth.currentUser!.providerData[1].email, equals(newEmail)); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => - auth.currentUser!.reauthenticateWithCredential(credential); - await testExceptionHandling('PLATFORM', callMethod); - }); - }); - - group('reload()', () { - test('should run successfully', () async { - // Setup - expect(auth.currentUser!.displayName, isNull); - user = generateUser( - user, {'displayName': 'test'}); // change mock user - - // Test - await auth.currentUser!.reload(); - - // Assumptions - expect( - log, - [ - isMethodCall( - 'User#reload', - arguments: { - 'appName': '[DEFAULT]', - 'tenantId': null, - }, - ) - ], - ); - expect(auth.currentUser!.displayName, 'test'); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => auth.currentUser!.reload(); - await testExceptionHandling('PLATFORM', callMethod); - }); - }); - group('sendEmailVerification()', () { - ActionCodeSettings actionCodeSettings = ActionCodeSettings(url: 'test'); - - test('should run successfully', () async { - // Test - await auth.currentUser!.sendEmailVerification(actionCodeSettings); - - // Assumptions - expect( - log, - [ - isMethodCall( - 'User#sendEmailVerification', - arguments: { - 'appName': '[DEFAULT]', - 'tenantId': null, - 'actionCodeSettings': actionCodeSettings.asMap() - }, - ) - ], - ); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => - auth.currentUser!.sendEmailVerification(actionCodeSettings); - await testExceptionHandling('PLATFORM', callMethod); - }); - }); - - group('unlink()', () { - test('should run successfully', () async { - expect(auth.currentUser!.providerData.length, equals(1)); - final unlinkedUser = await auth.currentUser!.unlink(kMockProviderId); - - expect( - log, - [ - isMethodCall( - 'User#unlink', - arguments: { - 'appName': '[DEFAULT]', - 'tenantId': null, - 'providerId': kMockProviderId - }, - ) - ], - ); - - expect(unlinkedUser, isA()); - expect(unlinkedUser.providerData.length, equals(0)); - - // check currentUser updated - expect(auth.currentUser!.providerData.length, equals(0)); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => auth.currentUser!.unlink(kMockProviderId); - await testExceptionHandling('PLATFORM', callMethod); - }); - }); - - group('updateEmail()', () { - const newEmail = 'new@email.com'; - - test('should run successfully', () async { - await auth.currentUser!.updateEmail(newEmail); - - expect( - log, - [ - isMethodCall( - 'User#updateEmail', - arguments: { - 'appName': '[DEFAULT]', - 'tenantId': null, - 'newEmail': newEmail - }, - ) - ], - ); - - await auth.currentUser!.reload(); - expect(auth.currentUser!.email, equals(newEmail)); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => auth.currentUser!.updateEmail(newEmail); - await testExceptionHandling('PLATFORM', callMethod); - }); - }); - - group('updatePassword()', () { - const newPassword = 'newPassword'; - - test('gets result successfully', () async { - await auth.currentUser!.updatePassword(newPassword); - - expect( - log[0], - isMethodCall( - 'User#updatePassword', - arguments: { - 'appName': '[DEFAULT]', - 'tenantId': null, - 'newPassword': newPassword - }, - ), - ); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => auth.currentUser!.updatePassword(newPassword); - await testExceptionHandling('PLATFORM', callMethod); - }); - }); - - group('updatePhoneNumber()', () { - PhoneAuthCredential phoneAuthCredential = PhoneAuthProvider.credential( - verificationId: 'test', - smsCode: 'test', - ); - - test('gets result successfully', () async { - await auth.currentUser!.updatePhoneNumber(phoneAuthCredential); - - expect( - log, - [ - isMethodCall( - 'User#updatePhoneNumber', - arguments: { - 'appName': '[DEFAULT]', - 'tenantId': null, - 'credential': { - 'providerId': 'phone', - 'signInMethod': 'phone', - 'verificationId': 'test', - 'smsCode': 'test', - 'token': null - } - }, - ) - ], - ); - - await auth.currentUser!.reload(); - expect(auth.currentUser!.phoneNumber, kMockNewPhoneNumber); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => - auth.currentUser!.updatePhoneNumber(phoneAuthCredential); - await testExceptionHandling('PLATFORM', callMethod); - }); - }); - - group('updateProfile()', () { - String newDisplayName = 'newDisplayName'; - String newPhotoURL = 'newPhotoURL'; - Map data = { - 'displayName': newDisplayName, - 'photoURL': newPhotoURL - }; - test('updateProfile()', () async { - await auth.currentUser!.updateProfile(data); - - expect( - log, - [ - isMethodCall( - 'User#updateProfile', - arguments: { - 'appName': '[DEFAULT]', - 'tenantId': null, - 'profile': { - 'displayName': newDisplayName, - 'photoURL': newPhotoURL, - } - }, - ) - ], - ); - - await auth.currentUser!.reload(); - expect(auth.currentUser!.displayName, equals(newDisplayName)); - expect(auth.currentUser!.photoURL, equals(newPhotoURL)); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => auth.currentUser!.updateProfile(data); - await testExceptionHandling('PLATFORM', callMethod); - }); - }); - - group('verifyBeforeUpdateEmail()', () { - final ActionCodeSettings actionCodeSettings = ActionCodeSettings( - url: 'test', - ); - const newEmail = 'new@email.com'; - test('verifyBeforeUpdateEmail()', () async { - await auth.currentUser! - .verifyBeforeUpdateEmail(newEmail, actionCodeSettings); - expect( - log, - [ - isMethodCall( - 'User#verifyBeforeUpdateEmail', - arguments: { - 'appName': '[DEFAULT]', - 'tenantId': null, - 'newEmail': newEmail, - 'actionCodeSettings': actionCodeSettings.asMap(), - }, - ) - ], - ); - }); - - test( - 'catch a [PlatformException] error and throws a [FirebaseAuthException] error', - () async { - mockPlatformExceptionThrown = true; - - void callMethod() => auth.currentUser! - .verifyBeforeUpdateEmail(newEmail, actionCodeSettings); - await testExceptionHandling('PLATFORM', callMethod); - }); - }); - }); -} diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/utils_tests/exception_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/utils_tests/exception_test.dart index 8d00393f785a..3c29573cb4fd 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/utils_tests/exception_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/utils_tests/exception_test.dart @@ -41,15 +41,16 @@ void main() { ); PlatformException platformException = PlatformException( - code: 'native', + code: 'unknown', message: 'PlatformException Message', details: { 'additionalData': {'authCredential': authCredential.asMap()} }); - FirebaseAuthException result = - platformExceptionToFirebaseAuthException(platformException) - as FirebaseAuthException; + FirebaseAuthException result = platformExceptionToFirebaseAuthException( + platformException, + fromPigeon: false, + ) as FirebaseAuthException; expect(result.code, equals('unknown')); expect(result.message, equals('PlatformException Message')); expect(result.email, isNull); @@ -77,9 +78,10 @@ void main() { } }); - FirebaseAuthException result = - platformExceptionToFirebaseAuthException(platformException) - as FirebaseAuthException; + FirebaseAuthException result = platformExceptionToFirebaseAuthException( + platformException, + fromPigeon: false, + ) as FirebaseAuthException; expect(result.code, equals('A Known Code')); expect(result.message, equals('A Known Message')); expect(result.email, 'test@email.com'); @@ -97,9 +99,10 @@ void main() { message: 'a message', ); - FirebaseAuthException result = - platformExceptionToFirebaseAuthException(platformException) - as FirebaseAuthException; + FirebaseAuthException result = platformExceptionToFirebaseAuthException( + platformException, + fromPigeon: false, + ) as FirebaseAuthException; expect(result.code, equals('unknown')); expect(result.message, equals('a message')); expect(result.email, null); @@ -113,9 +116,10 @@ void main() { message: 'a message', details: {'additionalData': null}); - FirebaseAuthException result = - platformExceptionToFirebaseAuthException(platformException) - as FirebaseAuthException; + FirebaseAuthException result = platformExceptionToFirebaseAuthException( + platformException, + fromPigeon: false, + ) as FirebaseAuthException; expect(result.code, equals('unknown')); expect(result.message, equals('a message')); expect(result.email, isNull); @@ -134,9 +138,10 @@ void main() { }, ); - FirebaseAuthException result = - platformExceptionToFirebaseAuthException(platformException) - as FirebaseAuthException; + FirebaseAuthException result = platformExceptionToFirebaseAuthException( + platformException, + fromPigeon: false, + ) as FirebaseAuthException; expect(result.code, equals('A Known Code')); expect(result.message, equals('A Known Message')); expect(result.email, 'test@email.com'); diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/mock.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/mock.dart index 755548e45d33..1b7b036ff1a8 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/mock.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/mock.dart @@ -88,12 +88,3 @@ Future testExceptionHandling( ]), ); } - -Map generateUser( - Map user, - Map updatedInfo, -) { - Map kMockUpdatedUser = Map.from(user); - kMockUpdatedUser.addAll(updatedInfo); - return kMockUpdatedUser; -} diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/pigeon/test_api.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/pigeon/test_api.dart index 37027578bd08..bcac1e158cea 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/pigeon/test_api.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/pigeon/test_api.dart @@ -1,32 +1,74 @@ -// Copyright 2022, the Chromium project authors. Please see the AUTHORS file +// Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v3.2.3), do not edit directly. +// Autogenerated from Pigeon (v9.2.4), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import // ignore_for_file: avoid_relative_lib_imports import 'dart:async'; -import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List; -import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import '../../lib/src/pigeon/messages.pigeon.dart'; +import 'package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart'; -class _TestMultiFactorUserHostApiCodec extends StandardMessageCodec { - const _TestMultiFactorUserHostApiCodec(); +class _TestFirebaseAuthHostApiCodec extends StandardMessageCodec { + const _TestFirebaseAuthHostApiCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonMultiFactorInfo) { + if (value is PigeonActionCodeInfo) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorSession) { + } else if (value is PigeonActionCodeInfoData) { buffer.putUint8(129); writeValue(buffer, value.encode()); - } else if (value is PigeonPhoneMultiFactorAssertion) { + } else if (value is PigeonActionCodeSettings) { buffer.putUint8(130); writeValue(buffer, value.encode()); + } else if (value is PigeonAdditionalUserInfo) { + buffer.putUint8(131); + writeValue(buffer, value.encode()); + } else if (value is PigeonAuthCredential) { + buffer.putUint8(132); + writeValue(buffer, value.encode()); + } else if (value is PigeonFirebaseApp) { + buffer.putUint8(133); + writeValue(buffer, value.encode()); + } else if (value is PigeonFirebaseAuthSettings) { + buffer.putUint8(134); + writeValue(buffer, value.encode()); + } else if (value is PigeonIdTokenResult) { + buffer.putUint8(135); + writeValue(buffer, value.encode()); + } else if (value is PigeonMultiFactorInfo) { + buffer.putUint8(136); + writeValue(buffer, value.encode()); + } else if (value is PigeonMultiFactorSession) { + buffer.putUint8(137); + writeValue(buffer, value.encode()); + } else if (value is PigeonPhoneMultiFactorAssertion) { + buffer.putUint8(138); + writeValue(buffer, value.encode()); + } else if (value is PigeonSignInProvider) { + buffer.putUint8(139); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserCredential) { + buffer.putUint8(140); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserDetails) { + buffer.putUint8(141); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserInfo) { + buffer.putUint8(142); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserProfile) { + buffer.putUint8(143); + writeValue(buffer, value.encode()); + } else if (value is PigeonVerifyPhoneNumberRequest) { + buffer.putUint8(144); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -36,14 +78,1219 @@ class _TestMultiFactorUserHostApiCodec extends StandardMessageCodec { Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { case 128: + return PigeonActionCodeInfo.decode(readValue(buffer)!); + case 129: + return PigeonActionCodeInfoData.decode(readValue(buffer)!); + case 130: + return PigeonActionCodeSettings.decode(readValue(buffer)!); + case 131: + return PigeonAdditionalUserInfo.decode(readValue(buffer)!); + case 132: + return PigeonAuthCredential.decode(readValue(buffer)!); + case 133: + return PigeonFirebaseApp.decode(readValue(buffer)!); + case 134: + return PigeonFirebaseAuthSettings.decode(readValue(buffer)!); + case 135: + return PigeonIdTokenResult.decode(readValue(buffer)!); + case 136: return PigeonMultiFactorInfo.decode(readValue(buffer)!); + case 137: + return PigeonMultiFactorSession.decode(readValue(buffer)!); + case 138: + return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); + case 139: + return PigeonSignInProvider.decode(readValue(buffer)!); + case 140: + return PigeonUserCredential.decode(readValue(buffer)!); + case 141: + return PigeonUserDetails.decode(readValue(buffer)!); + case 142: + return PigeonUserInfo.decode(readValue(buffer)!); + case 143: + return PigeonUserProfile.decode(readValue(buffer)!); + case 144: + return PigeonVerifyPhoneNumberRequest.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +abstract class TestFirebaseAuthHostApi { + static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => + TestDefaultBinaryMessengerBinding.instance; + static const MessageCodec codec = _TestFirebaseAuthHostApiCodec(); + + Future registerIdTokenListener(PigeonFirebaseApp app); + + Future registerAuthStateListener(PigeonFirebaseApp app); + + Future useEmulator(PigeonFirebaseApp app, String host, int port); + + Future applyActionCode(PigeonFirebaseApp app, String code); + + Future checkActionCode( + PigeonFirebaseApp app, String code); + + Future confirmPasswordReset( + PigeonFirebaseApp app, String code, String newPassword); + + Future createUserWithEmailAndPassword( + PigeonFirebaseApp app, String email, String password); + + Future signInAnonymously(PigeonFirebaseApp app); + + Future signInWithCredential( + PigeonFirebaseApp app, Map input); + + Future signInWithCustomToken( + PigeonFirebaseApp app, String token); + + Future signInWithEmailAndPassword( + PigeonFirebaseApp app, String email, String password); + + Future signInWithEmailLink( + PigeonFirebaseApp app, String email, String emailLink); + + Future signInWithProvider( + PigeonFirebaseApp app, PigeonSignInProvider signInProvider); + + Future signOut(PigeonFirebaseApp app); + + Future> fetchSignInMethodsForEmail( + PigeonFirebaseApp app, String email); + + Future sendPasswordResetEmail(PigeonFirebaseApp app, String email, + PigeonActionCodeSettings? actionCodeSettings); + + Future sendSignInLinkToEmail(PigeonFirebaseApp app, String email, + PigeonActionCodeSettings actionCodeSettings); + + Future setLanguageCode(PigeonFirebaseApp app, String? languageCode); + + Future setSettings( + PigeonFirebaseApp app, PigeonFirebaseAuthSettings settings); + + Future verifyPasswordResetCode(PigeonFirebaseApp app, String code); + + Future verifyPhoneNumber( + PigeonFirebaseApp app, PigeonVerifyPhoneNumberRequest request); + + static void setup(TestFirebaseAuthHostApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.registerIdTokenListener', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.registerIdTokenListener was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.registerIdTokenListener was null, expected non-null PigeonFirebaseApp.'); + final String output = await api.registerIdTokenListener(arg_app!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.registerAuthStateListener', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.registerAuthStateListener was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.registerAuthStateListener was null, expected non-null PigeonFirebaseApp.'); + final String output = await api.registerAuthStateListener(arg_app!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.useEmulator', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.useEmulator was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.useEmulator was null, expected non-null PigeonFirebaseApp.'); + final String? arg_host = (args[1] as String?); + assert(arg_host != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.useEmulator was null, expected non-null String.'); + final int? arg_port = (args[2] as int?); + assert(arg_port != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.useEmulator was null, expected non-null int.'); + await api.useEmulator(arg_app!, arg_host!, arg_port!); + return []; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.applyActionCode', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.applyActionCode was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.applyActionCode was null, expected non-null PigeonFirebaseApp.'); + final String? arg_code = (args[1] as String?); + assert(arg_code != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.applyActionCode was null, expected non-null String.'); + await api.applyActionCode(arg_app!, arg_code!); + return []; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.checkActionCode', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.checkActionCode was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.checkActionCode was null, expected non-null PigeonFirebaseApp.'); + final String? arg_code = (args[1] as String?); + assert(arg_code != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.checkActionCode was null, expected non-null String.'); + final PigeonActionCodeInfo output = + await api.checkActionCode(arg_app!, arg_code!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.confirmPasswordReset', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.confirmPasswordReset was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.confirmPasswordReset was null, expected non-null PigeonFirebaseApp.'); + final String? arg_code = (args[1] as String?); + assert(arg_code != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.confirmPasswordReset was null, expected non-null String.'); + final String? arg_newPassword = (args[2] as String?); + assert(arg_newPassword != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.confirmPasswordReset was null, expected non-null String.'); + await api.confirmPasswordReset(arg_app!, arg_code!, arg_newPassword!); + return []; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.createUserWithEmailAndPassword', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.createUserWithEmailAndPassword was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.createUserWithEmailAndPassword was null, expected non-null PigeonFirebaseApp.'); + final String? arg_email = (args[1] as String?); + assert(arg_email != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.createUserWithEmailAndPassword was null, expected non-null String.'); + final String? arg_password = (args[2] as String?); + assert(arg_password != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.createUserWithEmailAndPassword was null, expected non-null String.'); + final PigeonUserCredential output = + await api.createUserWithEmailAndPassword( + arg_app!, arg_email!, arg_password!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.signInAnonymously', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInAnonymously was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInAnonymously was null, expected non-null PigeonFirebaseApp.'); + final PigeonUserCredential output = + await api.signInAnonymously(arg_app!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.signInWithCredential', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithCredential was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithCredential was null, expected non-null PigeonFirebaseApp.'); + final Map? arg_input = + (args[1] as Map?)?.cast(); + assert(arg_input != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithCredential was null, expected non-null Map.'); + final PigeonUserCredential output = + await api.signInWithCredential(arg_app!, arg_input!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.signInWithCustomToken', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithCustomToken was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithCustomToken was null, expected non-null PigeonFirebaseApp.'); + final String? arg_token = (args[1] as String?); + assert(arg_token != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithCustomToken was null, expected non-null String.'); + final PigeonUserCredential output = + await api.signInWithCustomToken(arg_app!, arg_token!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailAndPassword', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailAndPassword was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailAndPassword was null, expected non-null PigeonFirebaseApp.'); + final String? arg_email = (args[1] as String?); + assert(arg_email != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailAndPassword was null, expected non-null String.'); + final String? arg_password = (args[2] as String?); + assert(arg_password != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailAndPassword was null, expected non-null String.'); + final PigeonUserCredential output = await api + .signInWithEmailAndPassword(arg_app!, arg_email!, arg_password!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailLink', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailLink was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailLink was null, expected non-null PigeonFirebaseApp.'); + final String? arg_email = (args[1] as String?); + assert(arg_email != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailLink was null, expected non-null String.'); + final String? arg_emailLink = (args[2] as String?); + assert(arg_emailLink != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithEmailLink was null, expected non-null String.'); + final PigeonUserCredential output = await api.signInWithEmailLink( + arg_app!, arg_email!, arg_emailLink!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.signInWithProvider', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithProvider was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithProvider was null, expected non-null PigeonFirebaseApp.'); + final PigeonSignInProvider? arg_signInProvider = + (args[1] as PigeonSignInProvider?); + assert(arg_signInProvider != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signInWithProvider was null, expected non-null PigeonSignInProvider.'); + final PigeonUserCredential output = + await api.signInWithProvider(arg_app!, arg_signInProvider!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.signOut', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signOut was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.signOut was null, expected non-null PigeonFirebaseApp.'); + await api.signOut(arg_app!); + return []; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.fetchSignInMethodsForEmail', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.fetchSignInMethodsForEmail was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.fetchSignInMethodsForEmail was null, expected non-null PigeonFirebaseApp.'); + final String? arg_email = (args[1] as String?); + assert(arg_email != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.fetchSignInMethodsForEmail was null, expected non-null String.'); + final List output = + await api.fetchSignInMethodsForEmail(arg_app!, arg_email!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.sendPasswordResetEmail', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.sendPasswordResetEmail was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.sendPasswordResetEmail was null, expected non-null PigeonFirebaseApp.'); + final String? arg_email = (args[1] as String?); + assert(arg_email != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.sendPasswordResetEmail was null, expected non-null String.'); + final PigeonActionCodeSettings? arg_actionCodeSettings = + (args[2] as PigeonActionCodeSettings?); + await api.sendPasswordResetEmail( + arg_app!, arg_email!, arg_actionCodeSettings); + return []; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.sendSignInLinkToEmail', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.sendSignInLinkToEmail was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.sendSignInLinkToEmail was null, expected non-null PigeonFirebaseApp.'); + final String? arg_email = (args[1] as String?); + assert(arg_email != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.sendSignInLinkToEmail was null, expected non-null String.'); + final PigeonActionCodeSettings? arg_actionCodeSettings = + (args[2] as PigeonActionCodeSettings?); + assert(arg_actionCodeSettings != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.sendSignInLinkToEmail was null, expected non-null PigeonActionCodeSettings.'); + await api.sendSignInLinkToEmail( + arg_app!, arg_email!, arg_actionCodeSettings!); + return []; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.setLanguageCode', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.setLanguageCode was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.setLanguageCode was null, expected non-null PigeonFirebaseApp.'); + final String? arg_languageCode = (args[1] as String?); + final String output = + await api.setLanguageCode(arg_app!, arg_languageCode); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.setSettings', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.setSettings was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.setSettings was null, expected non-null PigeonFirebaseApp.'); + final PigeonFirebaseAuthSettings? arg_settings = + (args[1] as PigeonFirebaseAuthSettings?); + assert(arg_settings != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.setSettings was null, expected non-null PigeonFirebaseAuthSettings.'); + await api.setSettings(arg_app!, arg_settings!); + return []; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.verifyPasswordResetCode', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.verifyPasswordResetCode was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.verifyPasswordResetCode was null, expected non-null PigeonFirebaseApp.'); + final String? arg_code = (args[1] as String?); + assert(arg_code != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.verifyPasswordResetCode was null, expected non-null String.'); + final String output = + await api.verifyPasswordResetCode(arg_app!, arg_code!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthHostApi.verifyPhoneNumber', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.verifyPhoneNumber was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.verifyPhoneNumber was null, expected non-null PigeonFirebaseApp.'); + final PigeonVerifyPhoneNumberRequest? arg_request = + (args[1] as PigeonVerifyPhoneNumberRequest?); + assert(arg_request != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthHostApi.verifyPhoneNumber was null, expected non-null PigeonVerifyPhoneNumberRequest.'); + final String output = + await api.verifyPhoneNumber(arg_app!, arg_request!); + return [output]; + }); + } + } + } +} + +class _TestFirebaseAuthUserHostApiCodec extends StandardMessageCodec { + const _TestFirebaseAuthUserHostApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonActionCodeInfo) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else if (value is PigeonActionCodeInfoData) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else if (value is PigeonActionCodeSettings) { + buffer.putUint8(130); + writeValue(buffer, value.encode()); + } else if (value is PigeonAdditionalUserInfo) { + buffer.putUint8(131); + writeValue(buffer, value.encode()); + } else if (value is PigeonAuthCredential) { + buffer.putUint8(132); + writeValue(buffer, value.encode()); + } else if (value is PigeonFirebaseApp) { + buffer.putUint8(133); + writeValue(buffer, value.encode()); + } else if (value is PigeonFirebaseAuthSettings) { + buffer.putUint8(134); + writeValue(buffer, value.encode()); + } else if (value is PigeonIdTokenResult) { + buffer.putUint8(135); + writeValue(buffer, value.encode()); + } else if (value is PigeonMultiFactorInfo) { + buffer.putUint8(136); + writeValue(buffer, value.encode()); + } else if (value is PigeonMultiFactorSession) { + buffer.putUint8(137); + writeValue(buffer, value.encode()); + } else if (value is PigeonPhoneMultiFactorAssertion) { + buffer.putUint8(138); + writeValue(buffer, value.encode()); + } else if (value is PigeonSignInProvider) { + buffer.putUint8(139); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserCredential) { + buffer.putUint8(140); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserDetails) { + buffer.putUint8(141); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserInfo) { + buffer.putUint8(142); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserProfile) { + buffer.putUint8(143); + writeValue(buffer, value.encode()); + } else if (value is PigeonVerifyPhoneNumberRequest) { + buffer.putUint8(144); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return PigeonActionCodeInfo.decode(readValue(buffer)!); case 129: + return PigeonActionCodeInfoData.decode(readValue(buffer)!); + case 130: + return PigeonActionCodeSettings.decode(readValue(buffer)!); + case 131: + return PigeonAdditionalUserInfo.decode(readValue(buffer)!); + case 132: + return PigeonAuthCredential.decode(readValue(buffer)!); + case 133: + return PigeonFirebaseApp.decode(readValue(buffer)!); + case 134: + return PigeonFirebaseAuthSettings.decode(readValue(buffer)!); + case 135: + return PigeonIdTokenResult.decode(readValue(buffer)!); + case 136: + return PigeonMultiFactorInfo.decode(readValue(buffer)!); + case 137: return PigeonMultiFactorSession.decode(readValue(buffer)!); + case 138: + return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); + case 139: + return PigeonSignInProvider.decode(readValue(buffer)!); + case 140: + return PigeonUserCredential.decode(readValue(buffer)!); + case 141: + return PigeonUserDetails.decode(readValue(buffer)!); + case 142: + return PigeonUserInfo.decode(readValue(buffer)!); + case 143: + return PigeonUserProfile.decode(readValue(buffer)!); + case 144: + return PigeonVerifyPhoneNumberRequest.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +abstract class TestFirebaseAuthUserHostApi { + static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => + TestDefaultBinaryMessengerBinding.instance; + static const MessageCodec codec = + _TestFirebaseAuthUserHostApiCodec(); + + Future delete(PigeonFirebaseApp app); + + Future getIdToken( + PigeonFirebaseApp app, bool forceRefresh); + + Future linkWithCredential( + PigeonFirebaseApp app, Map input); + + Future linkWithProvider( + PigeonFirebaseApp app, PigeonSignInProvider signInProvider); + + Future reauthenticateWithCredential( + PigeonFirebaseApp app, Map input); + + Future reauthenticateWithProvider( + PigeonFirebaseApp app, PigeonSignInProvider signInProvider); + + Future reload(PigeonFirebaseApp app); + + Future sendEmailVerification( + PigeonFirebaseApp app, PigeonActionCodeSettings? actionCodeSettings); + + Future unlink(PigeonFirebaseApp app, String providerId); + + Future updateEmail(PigeonFirebaseApp app, String newEmail); + + Future updatePassword( + PigeonFirebaseApp app, String newPassword); + + Future updatePhoneNumber( + PigeonFirebaseApp app, Map input); + + Future updateProfile( + PigeonFirebaseApp app, PigeonUserProfile profile); + + Future verifyBeforeUpdateEmail(PigeonFirebaseApp app, String newEmail, + PigeonActionCodeSettings? actionCodeSettings); + + static void setup(TestFirebaseAuthUserHostApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.delete', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.delete was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.delete was null, expected non-null PigeonFirebaseApp.'); + await api.delete(arg_app!); + return []; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.getIdToken', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.getIdToken was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.getIdToken was null, expected non-null PigeonFirebaseApp.'); + final bool? arg_forceRefresh = (args[1] as bool?); + assert(arg_forceRefresh != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.getIdToken was null, expected non-null bool.'); + final PigeonIdTokenResult output = + await api.getIdToken(arg_app!, arg_forceRefresh!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.linkWithCredential', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.linkWithCredential was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.linkWithCredential was null, expected non-null PigeonFirebaseApp.'); + final Map? arg_input = + (args[1] as Map?)?.cast(); + assert(arg_input != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.linkWithCredential was null, expected non-null Map.'); + final PigeonUserCredential output = + await api.linkWithCredential(arg_app!, arg_input!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.linkWithProvider', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.linkWithProvider was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.linkWithProvider was null, expected non-null PigeonFirebaseApp.'); + final PigeonSignInProvider? arg_signInProvider = + (args[1] as PigeonSignInProvider?); + assert(arg_signInProvider != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.linkWithProvider was null, expected non-null PigeonSignInProvider.'); + final PigeonUserCredential output = + await api.linkWithProvider(arg_app!, arg_signInProvider!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.reauthenticateWithCredential', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.reauthenticateWithCredential was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.reauthenticateWithCredential was null, expected non-null PigeonFirebaseApp.'); + final Map? arg_input = + (args[1] as Map?)?.cast(); + assert(arg_input != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.reauthenticateWithCredential was null, expected non-null Map.'); + final PigeonUserCredential output = + await api.reauthenticateWithCredential(arg_app!, arg_input!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.reauthenticateWithProvider', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.reauthenticateWithProvider was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.reauthenticateWithProvider was null, expected non-null PigeonFirebaseApp.'); + final PigeonSignInProvider? arg_signInProvider = + (args[1] as PigeonSignInProvider?); + assert(arg_signInProvider != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.reauthenticateWithProvider was null, expected non-null PigeonSignInProvider.'); + final PigeonUserCredential output = await api + .reauthenticateWithProvider(arg_app!, arg_signInProvider!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.reload', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.reload was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.reload was null, expected non-null PigeonFirebaseApp.'); + final PigeonUserDetails output = await api.reload(arg_app!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.sendEmailVerification', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.sendEmailVerification was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.sendEmailVerification was null, expected non-null PigeonFirebaseApp.'); + final PigeonActionCodeSettings? arg_actionCodeSettings = + (args[1] as PigeonActionCodeSettings?); + await api.sendEmailVerification(arg_app!, arg_actionCodeSettings); + return []; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.unlink', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.unlink was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.unlink was null, expected non-null PigeonFirebaseApp.'); + final String? arg_providerId = (args[1] as String?); + assert(arg_providerId != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.unlink was null, expected non-null String.'); + final PigeonUserCredential output = + await api.unlink(arg_app!, arg_providerId!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.updateEmail', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.updateEmail was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.updateEmail was null, expected non-null PigeonFirebaseApp.'); + final String? arg_newEmail = (args[1] as String?); + assert(arg_newEmail != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.updateEmail was null, expected non-null String.'); + final PigeonUserDetails output = + await api.updateEmail(arg_app!, arg_newEmail!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.updatePassword', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.updatePassword was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.updatePassword was null, expected non-null PigeonFirebaseApp.'); + final String? arg_newPassword = (args[1] as String?); + assert(arg_newPassword != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.updatePassword was null, expected non-null String.'); + final PigeonUserDetails output = + await api.updatePassword(arg_app!, arg_newPassword!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.updatePhoneNumber', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.updatePhoneNumber was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.updatePhoneNumber was null, expected non-null PigeonFirebaseApp.'); + final Map? arg_input = + (args[1] as Map?)?.cast(); + assert(arg_input != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.updatePhoneNumber was null, expected non-null Map.'); + final PigeonUserDetails output = + await api.updatePhoneNumber(arg_app!, arg_input!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.updateProfile', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.updateProfile was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.updateProfile was null, expected non-null PigeonFirebaseApp.'); + final PigeonUserProfile? arg_profile = + (args[1] as PigeonUserProfile?); + assert(arg_profile != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.updateProfile was null, expected non-null PigeonUserProfile.'); + final PigeonUserDetails output = + await api.updateProfile(arg_app!, arg_profile!); + return [output]; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FirebaseAuthUserHostApi.verifyBeforeUpdateEmail', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.verifyBeforeUpdateEmail was null.'); + final List args = (message as List?)!; + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.verifyBeforeUpdateEmail was null, expected non-null PigeonFirebaseApp.'); + final String? arg_newEmail = (args[1] as String?); + assert(arg_newEmail != null, + 'Argument for dev.flutter.pigeon.FirebaseAuthUserHostApi.verifyBeforeUpdateEmail was null, expected non-null String.'); + final PigeonActionCodeSettings? arg_actionCodeSettings = + (args[2] as PigeonActionCodeSettings?); + await api.verifyBeforeUpdateEmail( + arg_app!, arg_newEmail!, arg_actionCodeSettings); + return []; + }); + } + } + } +} +class _TestMultiFactorUserHostApiCodec extends StandardMessageCodec { + const _TestMultiFactorUserHostApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonFirebaseApp) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else if (value is PigeonMultiFactorInfo) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else if (value is PigeonMultiFactorSession) { + buffer.putUint8(130); + writeValue(buffer, value.encode()); + } else if (value is PigeonPhoneMultiFactorAssertion) { + buffer.putUint8(131); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return PigeonFirebaseApp.decode(readValue(buffer)!); + case 129: + return PigeonMultiFactorInfo.decode(readValue(buffer)!); case 130: + return PigeonMultiFactorSession.decode(readValue(buffer)!); + case 131: return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); - default: return super.readValueOfType(type, buffer); } @@ -51,13 +1298,20 @@ class _TestMultiFactorUserHostApiCodec extends StandardMessageCodec { } abstract class TestMultiFactorUserHostApi { + static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => + TestDefaultBinaryMessengerBinding.instance; static const MessageCodec codec = _TestMultiFactorUserHostApiCodec(); - Future enrollPhone(String appName, + Future enrollPhone(PigeonFirebaseApp app, PigeonPhoneMultiFactorAssertion assertion, String? displayName); - Future getSession(String appName); - Future unenroll(String appName, String? factorUid); - Future> getEnrolledFactors(String appName); + + Future getSession(PigeonFirebaseApp app); + + Future unenroll(PigeonFirebaseApp app, String factorUid); + + Future> getEnrolledFactors( + PigeonFirebaseApp app); + static void setup(TestMultiFactorUserHostApi? api, {BinaryMessenger? binaryMessenger}) { { @@ -65,22 +1319,25 @@ abstract class TestMultiFactorUserHostApi { 'dev.flutter.pigeon.MultiFactorUserHostApi.enrollPhone', codec, binaryMessenger: binaryMessenger); if (api == null) { - channel.setMockMessageHandler(null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); } else { - channel.setMockMessageHandler((Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { assert(message != null, 'Argument for dev.flutter.pigeon.MultiFactorUserHostApi.enrollPhone was null.'); final List args = (message as List?)!; - final String? arg_appName = (args[0] as String?); - assert(arg_appName != null, - 'Argument for dev.flutter.pigeon.MultiFactorUserHostApi.enrollPhone was null, expected non-null String.'); + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.MultiFactorUserHostApi.enrollPhone was null, expected non-null PigeonFirebaseApp.'); final PigeonPhoneMultiFactorAssertion? arg_assertion = (args[1] as PigeonPhoneMultiFactorAssertion?); assert(arg_assertion != null, 'Argument for dev.flutter.pigeon.MultiFactorUserHostApi.enrollPhone was null, expected non-null PigeonPhoneMultiFactorAssertion.'); final String? arg_displayName = (args[2] as String?); - await api.enrollPhone(arg_appName!, arg_assertion!, arg_displayName); - return {}; + await api.enrollPhone(arg_app!, arg_assertion!, arg_displayName); + return []; }); } } @@ -89,18 +1346,21 @@ abstract class TestMultiFactorUserHostApi { 'dev.flutter.pigeon.MultiFactorUserHostApi.getSession', codec, binaryMessenger: binaryMessenger); if (api == null) { - channel.setMockMessageHandler(null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); } else { - channel.setMockMessageHandler((Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { assert(message != null, 'Argument for dev.flutter.pigeon.MultiFactorUserHostApi.getSession was null.'); final List args = (message as List?)!; - final String? arg_appName = (args[0] as String?); - assert(arg_appName != null, - 'Argument for dev.flutter.pigeon.MultiFactorUserHostApi.getSession was null, expected non-null String.'); + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.MultiFactorUserHostApi.getSession was null, expected non-null PigeonFirebaseApp.'); final PigeonMultiFactorSession output = - await api.getSession(arg_appName!); - return {'result': output}; + await api.getSession(arg_app!); + return [output]; }); } } @@ -109,18 +1369,23 @@ abstract class TestMultiFactorUserHostApi { 'dev.flutter.pigeon.MultiFactorUserHostApi.unenroll', codec, binaryMessenger: binaryMessenger); if (api == null) { - channel.setMockMessageHandler(null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); } else { - channel.setMockMessageHandler((Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { assert(message != null, 'Argument for dev.flutter.pigeon.MultiFactorUserHostApi.unenroll was null.'); final List args = (message as List?)!; - final String? arg_appName = (args[0] as String?); - assert(arg_appName != null, - 'Argument for dev.flutter.pigeon.MultiFactorUserHostApi.unenroll was null, expected non-null String.'); + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.MultiFactorUserHostApi.unenroll was null, expected non-null PigeonFirebaseApp.'); final String? arg_factorUid = (args[1] as String?); - await api.unenroll(arg_appName!, arg_factorUid); - return {}; + assert(arg_factorUid != null, + 'Argument for dev.flutter.pigeon.MultiFactorUserHostApi.unenroll was null, expected non-null String.'); + await api.unenroll(arg_app!, arg_factorUid!); + return []; }); } } @@ -129,18 +1394,21 @@ abstract class TestMultiFactorUserHostApi { 'dev.flutter.pigeon.MultiFactorUserHostApi.getEnrolledFactors', codec, binaryMessenger: binaryMessenger); if (api == null) { - channel.setMockMessageHandler(null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); } else { - channel.setMockMessageHandler((Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { assert(message != null, 'Argument for dev.flutter.pigeon.MultiFactorUserHostApi.getEnrolledFactors was null.'); final List args = (message as List?)!; - final String? arg_appName = (args[0] as String?); - assert(arg_appName != null, - 'Argument for dev.flutter.pigeon.MultiFactorUserHostApi.getEnrolledFactors was null, expected non-null String.'); + final PigeonFirebaseApp? arg_app = (args[0] as PigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.MultiFactorUserHostApi.getEnrolledFactors was null, expected non-null PigeonFirebaseApp.'); final List output = - await api.getEnrolledFactors(arg_appName!); - return {'result': output}; + await api.getEnrolledFactors(arg_app!); + return [output]; }); } } @@ -151,15 +1419,24 @@ class _TestMultiFactoResolverHostApiCodec extends StandardMessageCodec { const _TestMultiFactoResolverHostApiCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonMultiFactorInfo) { + if (value is PigeonAdditionalUserInfo) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorSession) { + } else if (value is PigeonAuthCredential) { buffer.putUint8(129); writeValue(buffer, value.encode()); } else if (value is PigeonPhoneMultiFactorAssertion) { buffer.putUint8(130); writeValue(buffer, value.encode()); + } else if (value is PigeonUserCredential) { + buffer.putUint8(131); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserDetails) { + buffer.putUint8(132); + writeValue(buffer, value.encode()); + } else if (value is PigeonUserInfo) { + buffer.putUint8(133); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -169,14 +1446,17 @@ class _TestMultiFactoResolverHostApiCodec extends StandardMessageCodec { Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { case 128: - return PigeonMultiFactorInfo.decode(readValue(buffer)!); - + return PigeonAdditionalUserInfo.decode(readValue(buffer)!); case 129: - return PigeonMultiFactorSession.decode(readValue(buffer)!); - + return PigeonAuthCredential.decode(readValue(buffer)!); case 130: return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); - + case 131: + return PigeonUserCredential.decode(readValue(buffer)!); + case 132: + return PigeonUserDetails.decode(readValue(buffer)!); + case 133: + return PigeonUserInfo.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); } @@ -184,11 +1464,14 @@ class _TestMultiFactoResolverHostApiCodec extends StandardMessageCodec { } abstract class TestMultiFactoResolverHostApi { + static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => + TestDefaultBinaryMessengerBinding.instance; static const MessageCodec codec = _TestMultiFactoResolverHostApiCodec(); - Future> resolveSignIn( + Future resolveSignIn( String resolverId, PigeonPhoneMultiFactorAssertion assertion); + static void setup(TestMultiFactoResolverHostApi? api, {BinaryMessenger? binaryMessenger}) { { @@ -196,9 +1479,12 @@ abstract class TestMultiFactoResolverHostApi { 'dev.flutter.pigeon.MultiFactoResolverHostApi.resolveSignIn', codec, binaryMessenger: binaryMessenger); if (api == null) { - channel.setMockMessageHandler(null); + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); } else { - channel.setMockMessageHandler((Object? message) async { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { assert(message != null, 'Argument for dev.flutter.pigeon.MultiFactoResolverHostApi.resolveSignIn was null.'); final List args = (message as List?)!; @@ -209,9 +1495,9 @@ abstract class TestMultiFactoResolverHostApi { (args[1] as PigeonPhoneMultiFactorAssertion?); assert(arg_assertion != null, 'Argument for dev.flutter.pigeon.MultiFactoResolverHostApi.resolveSignIn was null, expected non-null PigeonPhoneMultiFactorAssertion.'); - final Map output = + final PigeonUserCredential output = await api.resolveSignIn(arg_resolverId!, arg_assertion!); - return {'result': output}; + return [output]; }); } } diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_auth_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_auth_test.dart index 8ced400ce84c..fd6ad03188b1 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_auth_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_auth_test.dart @@ -55,19 +55,6 @@ void main() { expect(firebaseAuthPlatform, isA()); }); - test('FirebaseAuthPlatform.instanceFor', () { - final result = FirebaseAuthPlatform.instanceFor( - app: app, - pluginConstants: { - 'APP_LANGUAGE_CODE': 'en', - 'APP_CURRENT_USER': {'uid': '1234'} - }); - expect(result, isA()); - expect(result.currentUser, isA()); - expect(result.currentUser!.uid, '1234'); - expect(result.languageCode, equals('en')); - }); - test('get.instance', () { expect(FirebaseAuthPlatform.instance, isA()); expect(FirebaseAuthPlatform.instance.app.name, diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_credential_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_credential_test.dart index 1afded4870d1..5adffbf2faf3 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_credential_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_credential_test.dart @@ -19,10 +19,16 @@ void main() { const String kMockEmail = 'test@example.com'; const String kMockPassword = 'test-password'; - final kMockUserData = { - 'uid': kMockUid, - 'email': kMockEmail, - }; + final kMockUserData = PigeonUserDetails( + userInfo: PigeonUserInfo( + uid: kMockUid, + email: kMockEmail, + isAnonymous: false, + isEmailVerified: false, + ), + providerData: [], + ); + group('$UserCredentialPlatform()', () { late AdditionalUserInfo kMockAdditionalUserInfo; late AuthCredential kMockCredential; @@ -97,7 +103,7 @@ void main() { class TestUserPlatform extends UserPlatform { TestUserPlatform(FirebaseAuthPlatform auth, - MultiFactorPlatform multiFactorPlatform, Map data) + MultiFactorPlatform multiFactorPlatform, PigeonUserDetails data) : super(auth, multiFactorPlatform, data); } diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_test.dart index 43cd0da0fe65..abc49090f128 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_test.dart @@ -27,38 +27,41 @@ void main() { DateTime.now().subtract(const Duration(days: 2)).millisecondsSinceEpoch; final int kMockLastSignInTimestamp = DateTime.now().subtract(const Duration(days: 1)).millisecondsSinceEpoch; - final List kMockInitialProviderData = [ - { + final List> kMockInitialProviderData = [ + { 'providerId': kMockProviderId, 'uid': kMockUid, 'displayName': kMockDisplayName, - 'photoURL': kMockPhotoURL, + 'photoUrl': kMockPhotoURL, 'email': kMockEmail, 'phoneNumber': kMockPhoneNumber, + 'isEmailVerified': false, + 'isAnonymous': true }, ]; group('$UserPlatform()', () { - Map kMockUser; + PigeonUserDetails kMockUser; setUpAll(() async { await Firebase.initializeApp(); auth = FirebaseAuthPlatform.instance; - kMockUser = { - 'uid': kMockUid, - 'isAnonymous': true, - 'email': kMockEmail, - 'displayName': kMockDisplayName, - 'emailVerified': false, - 'phoneNumber': kMockPhoneNumber, - 'metadata': { - 'creationTime': kMockCreationTimestamp, - 'lastSignInTime': kMockLastSignInTimestamp, - }, - 'photoURL': kMockPhotoURL, - 'providerData': kMockInitialProviderData, - 'refreshToken': kMockRefreshToken, - 'tenantId': kMockTenantId, - }; + kMockUser = PigeonUserDetails( + userInfo: PigeonUserInfo( + uid: kMockUid, + isAnonymous: true, + email: kMockEmail, + displayName: kMockDisplayName, + isEmailVerified: false, + phoneNumber: kMockPhoneNumber, + photoUrl: kMockPhotoURL, + refreshToken: kMockRefreshToken, + tenantId: kMockTenantId, + lastSignInTimestamp: kMockLastSignInTimestamp, + creationTimestamp: kMockCreationTimestamp, + ), + providerData: kMockInitialProviderData, + ); + userPlatform = TestUserPlatform(auth, TestMultiFactorPlatform(auth), kMockUser); }); @@ -92,8 +95,8 @@ void main() { test('UserPlatform.email', () { expect(userPlatform.email, kMockEmail); }); - test('UserPlatform.emailVerified', () { - expect(userPlatform.emailVerified, false); + test('UserPlatform.isEmailVerified', () { + expect(userPlatform.isEmailVerified, false); }); test('UserPlatform.isAnonymous', () { expect(userPlatform.isAnonymous, true); @@ -286,6 +289,6 @@ void main() { class TestUserPlatform extends UserPlatform { TestUserPlatform(FirebaseAuthPlatform auth, MultiFactorPlatform multiFactor, - Map data) + PigeonUserDetails data) : super(auth, multiFactor, data); } diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/providers_tests/github_auth_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/providers_tests/github_auth_test.dart index 65f43ad51ad8..72c40aa15a00 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/providers_tests/github_auth_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/providers_tests/github_auth_test.dart @@ -3,8 +3,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:flutter_test/flutter_test.dart'; import 'package:firebase_auth_platform_interface/firebase_auth_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; void main() { late TestGithubAuthProvider githubAuthProvider; @@ -51,7 +51,7 @@ void main() { group('setCustomParameters()', () { test('sets custom parameters', () { - final Map kCustomOAuthParameters = { + final Map kCustomOAuthParameters = { 'allow_signup': 'false', }; final result = diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/providers_tests/oauth_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/providers_tests/oauth_test.dart index 3c9cae33a76c..da2e71883969 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/providers_tests/oauth_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/providers_tests/oauth_test.dart @@ -3,8 +3,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:flutter_test/flutter_test.dart'; import 'package:firebase_auth_platform_interface/firebase_auth_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; const String kMockProviderId = 'test.com'; @@ -46,7 +46,7 @@ void main() { group('setCustomParameters()', () { test('sets custom parameters', () { - final Map kCustomOAuthParameters = { + final Map kCustomOAuthParameters = { 'allow_signup': 'false', }; final result = diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/providers_tests/twitter_auth_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/providers_tests/twitter_auth_test.dart index 020649493039..dd1462f2fc94 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/providers_tests/twitter_auth_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/providers_tests/twitter_auth_test.dart @@ -3,8 +3,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:flutter_test/flutter_test.dart'; import 'package:firebase_auth_platform_interface/firebase_auth_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; void main() { late TestTwitterAuthProvider twitterAuthProvider; @@ -35,9 +35,7 @@ void main() { group('setCustomParameters()', () { test('sets custom parameters', () { - final Map kCustomOAuthParameters = { - 'lang': 'es' - }; + final Map kCustomOAuthParameters = {'lang': 'es'}; final result = twitterAuthProvider.setCustomParameters(kCustomOAuthParameters); expect(result, isA()); diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/user_info_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/user_info_test.dart index a824777703fa..869eea804b14 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/user_info_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/user_info_test.dart @@ -16,17 +16,20 @@ void main() { const String kMockEmail = 'test@example.com'; const String kMockPhoneNumber = TEST_PHONE_NUMBER; - const Map kMockData = { + + const Map kMockData = { 'providerId': kMockProviderId, 'uid': kMockUid, 'displayName': kMockDisplayName, - 'photoURL': kMockPhotoURL, + 'photoUrl': kMockPhotoURL, 'email': kMockEmail, - 'phoneNumber': kMockPhoneNumber + 'phoneNumber': kMockPhoneNumber, + 'isAnonymous': false, + 'isEmailVerified': false, }; group('$UserInfo', () { - final userInfo = UserInfo(kMockData); + final userInfo = UserInfo.fromJson(kMockData); group('Constructor', () { test('returns an instance of [UserInfo]', () { expect(userInfo, isA()); diff --git a/packages/firebase_auth/firebase_auth_web/lib/firebase_auth_web.dart b/packages/firebase_auth/firebase_auth_web/lib/firebase_auth_web.dart index 953ef077a39f..035cf86ab8b1 100644 --- a/packages/firebase_auth/firebase_auth_web/lib/firebase_auth_web.dart +++ b/packages/firebase_auth/firebase_auth_web/lib/firebase_auth_web.dart @@ -161,7 +161,7 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform { @override FirebaseAuthWeb setInitialValues({ - Map? currentUser, + PigeonUserDetails? currentUser, String? languageCode, }) { // Values are already set on web diff --git a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_web_user.dart b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_web_user.dart index b071b1167171..641445e2e6d5 100644 --- a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_web_user.dart +++ b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_web_user.dart @@ -21,37 +21,40 @@ class UserWeb extends UserPlatform { MultiFactorPlatform multiFactor, this._webUser, this._webAuth, - ) : super(auth, multiFactor, { - 'displayName': _webUser.displayName, - 'email': _webUser.email, - 'emailVerified': _webUser.emailVerified, - 'isAnonymous': _webUser.isAnonymous, - 'metadata': { - 'creationTime': _webUser.metadata.creationTime != null - ? context['Date'] - .callMethod('parse', [_webUser.metadata.creationTime]) - : null, - 'lastSignInTime': _webUser.metadata.lastSignInTime != null - ? context['Date'] - .callMethod('parse', [_webUser.metadata.lastSignInTime]) - : null, - }, - 'phoneNumber': _webUser.phoneNumber, - 'photoURL': _webUser.photoURL, - 'providerData': _webUser.providerData - .map((auth_interop.UserInfo webUserInfo) => { - 'displayName': webUserInfo.displayName, - 'email': webUserInfo.email, - 'phoneNumber': webUserInfo.phoneNumber, - 'providerId': webUserInfo.providerId, - 'photoURL': webUserInfo.photoURL, - 'uid': webUserInfo.uid, - }) - .toList(), - 'refreshToken': _webUser.refreshToken, - 'tenantId': _webUser.tenantId, - 'uid': _webUser.uid, - }); + ) : super( + auth, + multiFactor, + PigeonUserDetails( + userInfo: PigeonUserInfo( + displayName: _webUser.displayName, + email: _webUser.email, + isEmailVerified: _webUser.emailVerified, + isAnonymous: _webUser.isAnonymous, + creationTimestamp: _webUser.metadata.creationTime != null + ? context['Date'] + .callMethod('parse', [_webUser.metadata.creationTime]) + : null, + lastSignInTimestamp: _webUser.metadata.lastSignInTime != null + ? context['Date'] + .callMethod('parse', [_webUser.metadata.lastSignInTime]) + : null, + phoneNumber: _webUser.phoneNumber, + photoUrl: _webUser.photoURL, + refreshToken: _webUser.refreshToken, + tenantId: _webUser.tenantId, + uid: _webUser.uid, + ), + providerData: _webUser.providerData + .map((auth_interop.UserInfo webUserInfo) => { + 'displayName': webUserInfo.displayName, + 'email': webUserInfo.email, + 'phoneNumber': webUserInfo.phoneNumber, + 'providerId': webUserInfo.providerId, + 'photoUrl': webUserInfo.photoURL, + 'uid': webUserInfo.uid, + }) + .toList()), + ); final auth_interop.User _webUser; final auth_interop.Auth? _webAuth; diff --git a/packages/firebase_auth/firebase_auth_web/lib/src/utils/web_utils.dart b/packages/firebase_auth/firebase_auth_web/lib/src/utils/web_utils.dart index 5945a9b44879..335e1e20603b 100644 --- a/packages/firebase_auth/firebase_auth_web/lib/src/utils/web_utils.dart +++ b/packages/firebase_auth/firebase_auth_web/lib/src/utils/web_utils.dart @@ -101,10 +101,13 @@ ActionCodeInfo? convertWebActionCodeInfo( return null; } - return ActionCodeInfo(operation: 0, data: { - 'email': webActionCodeInfo.data.email, - 'previousEmail': webActionCodeInfo.data.previousEmail, - }); + return ActionCodeInfo( + operation: ActionCodeInfoOperation.passwordReset, + data: ActionCodeInfoData( + email: webActionCodeInfo.data.email, + previousEmail: webActionCodeInfo.data.previousEmail, + ), + ); } /// Converts a [auth_interop.AdditionalUserInfo] into a [AdditionalUserInfo]. @@ -127,16 +130,17 @@ AdditionalUserInfo? convertWebAdditionalUserInfo( IdTokenResult convertWebIdTokenResult( auth_interop.IdTokenResult webIdTokenResult, ) { - return IdTokenResult({ - 'claims': webIdTokenResult.claims, - 'expirationTimestamp': - webIdTokenResult.expirationTime.millisecondsSinceEpoch, - 'issuedAtTimestamp': webIdTokenResult.issuedAtTime.millisecondsSinceEpoch, - 'authTimestamp': webIdTokenResult.authTime.millisecondsSinceEpoch, - 'signInProvider': webIdTokenResult.signInProvider, - 'signInSecondFactor': null, - 'token': webIdTokenResult.token, - }); + return IdTokenResult( + PigeonIdTokenResult( + claims: webIdTokenResult.claims, + token: webIdTokenResult.token, + authTimestamp: webIdTokenResult.authTime.millisecondsSinceEpoch, + issuedAtTimestamp: webIdTokenResult.issuedAtTime.millisecondsSinceEpoch, + expirationTimestamp: + webIdTokenResult.expirationTime.millisecondsSinceEpoch, + signInProvider: webIdTokenResult.signInProvider, + ), + ); } /// Converts a [ActionCodeSettings] into a [auth_interop.ActionCodeSettings]. diff --git a/packages/firebase_ui_auth/doc/providers/email-verification.md b/packages/firebase_ui_auth/doc/providers/email-verification.md index 3b0f375bc0c4..3b603ed921bd 100644 --- a/packages/firebase_ui_auth/doc/providers/email-verification.md +++ b/packages/firebase_ui_auth/doc/providers/email-verification.md @@ -15,7 +15,7 @@ class App extends StatelessWidget { return SignInScreen( actions: [ AuthStateChangeAction((context, state) { - if (!state.user!.emailVerified) { + if (!state.user!.isEmailVerified) { Navigator.pushNamed(context, '/verify-email'); } else { Navigator.pushReplacementNamed(context, '/profile'); diff --git a/packages/firebase_ui_auth/doc/providers/email.md b/packages/firebase_ui_auth/doc/providers/email.md index 3d88ec5b1a5e..a5749f36a19e 100644 --- a/packages/firebase_ui_auth/doc/providers/email.md +++ b/packages/firebase_ui_auth/doc/providers/email.md @@ -37,7 +37,7 @@ After adding `EmailAuthProvider` to the `FirebaseUIAuth.configureProviders` emai SignInScreen( actions: [ AuthStateChangeAction((context, state) { - if (!state.user!.emailVerified) { + if (!state.user!.isEmailVerified) { Navigator.pushNamed(context, '/verify-email'); } else { Navigator.pushReplacementNamed(context, '/profile'); @@ -69,7 +69,7 @@ class MyLoginScreen extends StatelessWidget { child: FirebaseUIActions( actions: [ AuthStateChangeAction((context, state) { - if (!state.user!.emailVerified) { + if (!state.user!.isEmailVerified) { Navigator.pushNamed(context, '/verify-email'); } else { Navigator.pushReplacementNamed(context, '/profile'); diff --git a/packages/firebase_ui_auth/example/test_driver/layout_test.dart b/packages/firebase_ui_auth/example/test_driver/layout_test.dart index 0af093d48c9c..b17502a954b9 100644 --- a/packages/firebase_ui_auth/example/test_driver/layout_test.dart +++ b/packages/firebase_ui_auth/example/test_driver/layout_test.dart @@ -50,10 +50,10 @@ void main() { class MockUser extends Mock implements User { @override List get providerData => [ - UserInfo({'providerId': 'password'}), - UserInfo({'providerId': 'google.com'}), - UserInfo({'providerId': 'apple.com'}), - UserInfo({'providerId': 'phone'}) + UserInfo.fromJson({'providerId': 'password'}), + UserInfo.fromJson({'providerId': 'google.com'}), + UserInfo.fromJson({'providerId': 'apple.com'}), + UserInfo.fromJson({'providerId': 'phone'}) ]; } diff --git a/packages/firebase_ui_auth/lib/src/auth_state.dart b/packages/firebase_ui_auth/lib/src/auth_state.dart index 9ffd33aeb58a..776385dbc2b8 100644 --- a/packages/firebase_ui_auth/lib/src/auth_state.dart +++ b/packages/firebase_ui_auth/lib/src/auth_state.dart @@ -2,10 +2,10 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:firebase_ui_auth/firebase_ui_auth.dart'; -import 'package:flutter/widgets.dart'; import 'package:firebase_auth/firebase_auth.dart' show AuthCredential, MultiFactorResolver, User, UserCredential; +import 'package:firebase_ui_auth/firebase_ui_auth.dart'; +import 'package:flutter/widgets.dart'; /// An abstract class for all auth states. /// [AuthState] transitions could be captured with an [AuthStateChangeAction]: @@ -15,7 +15,7 @@ import 'package:firebase_auth/firebase_auth.dart' /// actions: [ /// AuthStateChangeAction((context, state) { /// print(state.user!.displayName); -/// print(state.user!.emailVerified); +/// print(state.user!.isEmailVerified); /// }), /// ], /// ); diff --git a/packages/firebase_ui_auth/lib/src/screens/register_screen.dart b/packages/firebase_ui_auth/lib/src/screens/register_screen.dart index 646d5fad8a3b..9208ba10f3a9 100644 --- a/packages/firebase_ui_auth/lib/src/screens/register_screen.dart +++ b/packages/firebase_ui_auth/lib/src/screens/register_screen.dart @@ -2,8 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:flutter/material.dart'; import 'package:firebase_ui_auth/firebase_ui_auth.dart'; +import 'package:flutter/material.dart'; import 'internal/login_screen.dart'; import 'internal/multi_provider_screen.dart'; @@ -47,7 +47,7 @@ class RegisterScreen extends MultiProviderScreen { /// Navigator.pushNamed(context, '/phone'); /// }), /// AuthStateChangeAction((context, state) { - /// if (!state.user!.emailVerified) { + /// if (!state.user!.isEmailVerified) { /// Navigator.pushNamed(context, '/verify-email'); /// } else { /// Navigator.pushReplacementNamed(context, '/profile'); diff --git a/packages/firebase_ui_auth/lib/src/screens/sign_in_screen.dart b/packages/firebase_ui_auth/lib/src/screens/sign_in_screen.dart index 5a67e2ac7724..970a5df3a46b 100644 --- a/packages/firebase_ui_auth/lib/src/screens/sign_in_screen.dart +++ b/packages/firebase_ui_auth/lib/src/screens/sign_in_screen.dart @@ -2,8 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:flutter/material.dart'; import 'package:firebase_ui_auth/firebase_ui_auth.dart'; +import 'package:flutter/material.dart'; import 'internal/login_screen.dart'; import 'internal/multi_provider_screen.dart'; @@ -72,7 +72,7 @@ class SignInScreen extends MultiProviderScreen { /// Navigator.pushNamed(context, '/phone'); /// }), /// AuthStateChangeAction((context, state) { - /// if (!state.user!.emailVerified) { + /// if (!state.user!.isEmailVerified) { /// Navigator.pushNamed(context, '/verify-email'); /// } else { /// Navigator.pushReplacementNamed(context, '/profile'); diff --git a/tests/android/build.gradle b/tests/android/build.gradle index 732b266aec33..5aaf6b10f869 100644 --- a/tests/android/build.gradle +++ b/tests/android/build.gradle @@ -30,6 +30,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/tests/integration_test/e2e_test.dart b/tests/integration_test/e2e_test.dart index 04c98b2deba8..921fb80bc785 100644 --- a/tests/integration_test/e2e_test.dart +++ b/tests/integration_test/e2e_test.dart @@ -53,7 +53,7 @@ void main() { firebase_storage.main(); } else { // Only tests available on Windows - firebase_core.main(); + firebase_core.main(); } }); } diff --git a/tests/integration_test/firebase_auth/firebase_auth_instance_e2e_test.dart b/tests/integration_test/firebase_auth/firebase_auth_instance_e2e_test.dart index 871adcc918cc..b63a31869830 100644 --- a/tests/integration_test/firebase_auth/firebase_auth_instance_e2e_test.dart +++ b/tests/integration_test/firebase_auth/firebase_auth_instance_e2e_test.dart @@ -425,16 +425,16 @@ void main() { ); // Confirm with the emulator that it triggered an email sending code. - final oobCode = (await emulatorOutOfBandCode( + final oobCode = await emulatorOutOfBandCode( email, EmulatorOobCodeType.emailSignIn, - ))!; + ); expect(oobCode, isNotNull); - expect(oobCode.email, email); - expect(oobCode.type, EmulatorOobCodeType.emailSignIn); + expect(oobCode?.email, email); + expect(oobCode?.type, EmulatorOobCodeType.emailSignIn); // Confirm the continue url was passed through to backend correctly. - final url = Uri.parse(oobCode.oobLink!); + final url = Uri.parse(oobCode!.oobLink!); expect( url.queryParameters['continueUrl'], Uri.encodeFull(continueUrl), @@ -527,7 +527,7 @@ void main() { group('signInWithCredential()', () { test('should login with email and password', () async { - var credential = EmailAuthProvider.credential( + final credential = EmailAuthProvider.credential( email: testEmail, password: testPassword, ); @@ -537,7 +537,7 @@ void main() { }); test('throws if login user is disabled', () async { - var credential = EmailAuthProvider.credential( + final credential = EmailAuthProvider.credential( email: testDisabledEmail, password: testPassword, ); @@ -580,7 +580,7 @@ void main() { }); test('throws if login user is not found', () async { - var credential = EmailAuthProvider.credential( + final credential = EmailAuthProvider.credential( email: generateRandomEmail(), password: testPassword, ); diff --git a/tests/integration_test/firebase_auth/firebase_auth_user_e2e_test.dart b/tests/integration_test/firebase_auth/firebase_auth_user_e2e_test.dart index f97277056d85..022198b48459 100644 --- a/tests/integration_test/firebase_auth/firebase_auth_user_e2e_test.dart +++ b/tests/integration_test/firebase_auth/firebase_auth_user_e2e_test.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; + import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -13,268 +14,244 @@ import 'test_utils.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - group('$User', () { - String email = generateRandomEmail(); - - group('getIdToken()', () { - test('should return a token', () async { - // Setup - User? user; - UserCredential userCredential; + group( + '$User', + () { + String email = generateRandomEmail(); - userCredential = - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: testPassword, - ); - user = userCredential.user; - - // Test - String token = await user!.getIdToken(); + group('getIdToken()', () { + test('should return a token', () async { + // Setup + User? user; + UserCredential userCredential; - // // Assertions - expect(token.length, greaterThan(24)); - }); + userCredential = + await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: email, + password: testPassword, + ); + user = userCredential.user; - test('should catch error', () async { - // Setup - late User user; - UserCredential userCredential; + // Test + String? token = await user!.getIdToken(); - userCredential = - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: testPassword, - ); - user = userCredential.user!; + // // Assertions + expect(token?.length, greaterThan(24)); + }); - // needed for method to throw an error - await FirebaseAuth.instance.signOut(); + test('should catch error', () async { + // Setup + late User user; + UserCredential userCredential; - try { - // Test - await user.getIdToken(); - } on FirebaseAuthException catch (_) { - return; - } catch (e) { - fail('should have thrown a FirebaseAuthException error'); - } - fail('should have thrown an error'); - }); - }); + userCredential = + await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: email, + password: testPassword, + ); + user = userCredential.user!; - group('getIdTokenResult()', () { - test('should return a valid IdTokenResult Object', () async { - // Setup - late User user; - UserCredential userCredential; + // needed for method to throw an error + await FirebaseAuth.instance.signOut(); - userCredential = - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: testPassword, - ); - user = userCredential.user!; - - // Test - final idTokenResult = await user.getIdTokenResult(); - - // Assertions - expect(idTokenResult.token.runtimeType, equals(String)); - expect(idTokenResult.authTime.runtimeType, equals(DateTime)); - expect(idTokenResult.issuedAtTime.runtimeType, equals(DateTime)); - expect(idTokenResult.expirationTime.runtimeType, equals(DateTime)); - expect(idTokenResult.token!.length, greaterThan(24)); - expect(idTokenResult.signInProvider, equals('password')); + try { + // Test + await user.getIdToken(); + } on FirebaseAuthException catch (_) { + return; + } catch (e) { + fail('should have thrown a FirebaseAuthException error'); + } + fail('should have thrown an error'); + }); }); - // TODO add custom claims and tenant id tests for id token result - }); - group('linkWithCredential()', () { - test('should link anonymous account <-> email account', () async { - await FirebaseAuth.instance.signInAnonymously(); - String currentUID = FirebaseAuth.instance.currentUser!.uid; + group('getIdTokenResult()', () { + test('should return a valid IdTokenResult Object', () async { + // Setup + late User user; + UserCredential userCredential; - UserCredential linkedUserCredential = - await FirebaseAuth.instance.currentUser!.linkWithCredential( - EmailAuthProvider.credential( + userCredential = + await FirebaseAuth.instance.createUserWithEmailAndPassword( email: email, password: testPassword, - ), - ); + ); + user = userCredential.user!; - User linkedUser = linkedUserCredential.user!; - expect(linkedUser.email, equals(email)); - expect( - linkedUser.email, - equals(FirebaseAuth.instance.currentUser!.email), - ); - expect(linkedUser.uid, equals(currentUID)); - expect(linkedUser.isAnonymous, isFalse); - }); + // Test + final idTokenResult = await user.getIdTokenResult(); - test('should error on link anon <-> email if email already exists', - () async { - // Setup + // Assertions + expect(idTokenResult.token.runtimeType, equals(String)); + expect(idTokenResult.authTime.runtimeType, equals(DateTime)); + expect(idTokenResult.issuedAtTime.runtimeType, equals(DateTime)); + expect(idTokenResult.expirationTime.runtimeType, equals(DateTime)); + expect(idTokenResult.token!.length, greaterThan(24)); + expect(idTokenResult.signInProvider, equals('password')); + }); + // TODO add custom claims and tenant id tests for id token result + }); - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: testPassword, - ); - await FirebaseAuth.instance.signInAnonymously(); + group('linkWithCredential()', () { + test('should link anonymous account <-> email account', () async { + await FirebaseAuth.instance.signInAnonymously(); + String currentUID = FirebaseAuth.instance.currentUser!.uid; - // Test - try { - await FirebaseAuth.instance.currentUser!.linkWithCredential( + UserCredential linkedUserCredential = + await FirebaseAuth.instance.currentUser!.linkWithCredential( EmailAuthProvider.credential( email: email, password: testPassword, ), ); - } on FirebaseAuthException catch (e) { - // Assertions - expect(e.code, 'email-already-in-use'); + + User linkedUser = linkedUserCredential.user!; + expect(linkedUser.email, equals(email)); expect( - e.message, - 'The email address is already in use by another account.', + linkedUser.email, + equals(FirebaseAuth.instance.currentUser!.email), ); + expect(linkedUser.uid, equals(currentUID)); + expect(linkedUser.isAnonymous, isFalse); + }); - // clean up - await FirebaseAuth.instance.currentUser!.delete(); - return; - } - - fail('should have thrown an error'); - }); - - test( - 'should link anonymous account <-> phone account', - () async { - await FirebaseAuth.instance.signInAnonymously(); - - Future getVerificationId() { - Completer completer = Completer(); - - unawaited( - FirebaseAuth.instance.verifyPhoneNumber( - phoneNumber: testPhoneNumber, - verificationCompleted: (PhoneAuthCredential credential) { - fail('Should not have auto resolved'); - }, - verificationFailed: (FirebaseException e) { - fail('Should not have errored: $e'); - }, - codeSent: (String verificationId, int? resetToken) { - completer.complete(verificationId); - }, - codeAutoRetrievalTimeout: (String foo) {}, - ), - ); - - return completer.future.then((value) => value as String); - } - - String storedVerificationId = await getVerificationId(); + test('should error on link anon <-> email if email already exists', + () async { + // Setup - await FirebaseAuth.instance.currentUser!.linkWithCredential( - PhoneAuthProvider.credential( - verificationId: storedVerificationId, - smsCode: (await emulatorPhoneVerificationCode(testPhoneNumber))!, - ), - ); - expect(FirebaseAuth.instance.currentUser, equals(isA())); - expect( - FirebaseAuth.instance.currentUser!.phoneNumber, - equals(testPhoneNumber), - ); - expect( - FirebaseAuth.instance.currentUser!.providerData, - equals(isA>()), - ); - expect( - FirebaseAuth.instance.currentUser!.providerData.length, - equals(1), + await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: email, + password: testPassword, ); - expect( - FirebaseAuth.instance.currentUser!.providerData[0], - equals(isA()), - ); - expect(FirebaseAuth.instance.currentUser!.isAnonymous, isFalse); - await FirebaseAuth.instance.currentUser - ?.unlink(PhoneAuthProvider.PROVIDER_ID); - await FirebaseAuth.instance.currentUser?.delete(); - }, - skip: kIsWeb || defaultTargetPlatform == TargetPlatform.macOS, - ); // verifyPhoneNumber not supported on web. - - test( - 'should error on link anonymous account <-> phone account if invalid credentials', - () async { - // Setup await FirebaseAuth.instance.signInAnonymously(); + // Test try { await FirebaseAuth.instance.currentUser!.linkWithCredential( - PhoneAuthProvider.credential( - verificationId: 'test', - smsCode: 'test', + EmailAuthProvider.credential( + email: email, + password: testPassword, ), ); } on FirebaseAuthException catch (e) { - expect(e.code, equals('invalid-verification-id')); + // Assertions + expect(e.code, 'email-already-in-use'); expect( e.message, - equals( - 'The verification ID used to create the phone auth credential is invalid.', - ), + 'The email address is already in use by another account.', ); + + // clean up + await FirebaseAuth.instance.currentUser!.delete(); return; - } catch (e) { - fail('should have thrown an FirebaseAuthException'); } fail('should have thrown an error'); - }, - skip: defaultTargetPlatform == TargetPlatform.macOS, - ); - }); - - group('reauthenticateWithCredential()', () { - test('should reauthenticate correctly', () async { - // Setup - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: testPassword, - ); - User initialUser = FirebaseAuth.instance.currentUser!; - - // Test - AuthCredential credential = - EmailAuthProvider.credential(email: email, password: testPassword); - await FirebaseAuth.instance.currentUser! - .reauthenticateWithCredential(credential); - - // Assertions - User currentUser = FirebaseAuth.instance.currentUser!; - expect(currentUser.email, equals(email)); - expect(currentUser.uid, equals(initialUser.uid)); - }); + }); - test('should throw user-mismatch ', () async { - // Setup - String emailAlready = generateRandomEmail(); + test( + 'should link anonymous account <-> phone account', + () async { + await FirebaseAuth.instance.signInAnonymously(); + + Future getVerificationId() { + Completer completer = Completer(); + + unawaited( + FirebaseAuth.instance.verifyPhoneNumber( + phoneNumber: testPhoneNumber, + verificationCompleted: (PhoneAuthCredential credential) { + fail('Should not have auto resolved'); + }, + verificationFailed: (FirebaseException e) { + fail('Should not have errored: $e'); + }, + codeSent: (String verificationId, int? resetToken) { + completer.complete(verificationId); + }, + codeAutoRetrievalTimeout: (String foo) {}, + ), + ); + + return completer.future.then((value) => value as String); + } + + String storedVerificationId = await getVerificationId(); - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: testPassword, + await FirebaseAuth.instance.currentUser!.linkWithCredential( + PhoneAuthProvider.credential( + verificationId: storedVerificationId, + smsCode: + (await emulatorPhoneVerificationCode(testPhoneNumber))!, + ), + ); + expect(FirebaseAuth.instance.currentUser, equals(isA())); + expect( + FirebaseAuth.instance.currentUser!.phoneNumber, + equals(testPhoneNumber), + ); + expect( + FirebaseAuth.instance.currentUser!.providerData, + equals(isA>()), + ); + expect( + FirebaseAuth.instance.currentUser!.providerData.length, + equals(1), + ); + expect( + FirebaseAuth.instance.currentUser!.providerData[0], + equals(isA()), + ); + expect(FirebaseAuth.instance.currentUser!.isAnonymous, isFalse); + await FirebaseAuth.instance.currentUser + ?.unlink(PhoneAuthProvider.PROVIDER_ID); + await FirebaseAuth.instance.currentUser?.delete(); + }, + skip: kIsWeb || defaultTargetPlatform == TargetPlatform.macOS, + ); // verifyPhoneNumber not supported on web. + + test( + 'should error on link anonymous account <-> phone account if invalid credentials', + () async { + // Setup + await FirebaseAuth.instance.signInAnonymously(); + + try { + await FirebaseAuth.instance.currentUser!.linkWithCredential( + PhoneAuthProvider.credential( + verificationId: 'test', + smsCode: 'test', + ), + ); + } on FirebaseAuthException catch (e) { + expect(e.code, equals('invalid-verification-id')); + expect( + e.message, + equals( + 'The verification ID used to create the phone auth credential is invalid.', + ), + ); + return; + } catch (e) { + fail('should have thrown an FirebaseAuthException'); + } + + fail('should have thrown an error'); + }, + skip: defaultTargetPlatform == TargetPlatform.macOS, ); + }); - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: emailAlready, - password: testPassword, - ); + group('reauthenticateWithCredential()', () { + test('should reauthenticate correctly', () async { + // Setup + await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: email, + password: testPassword, + ); + User initialUser = FirebaseAuth.instance.currentUser!; - try { // Test AuthCredential credential = EmailAuthProvider.credential( email: email, @@ -282,407 +259,408 @@ void main() { ); await FirebaseAuth.instance.currentUser! .reauthenticateWithCredential(credential); - } on FirebaseAuthException catch (e) { + // Assertions - expect(e.code, equals('user-mismatch')); - expect( - e.message, - equals( - 'The supplied credentials do not correspond to the previously signed in user.', - ), - ); - await FirebaseAuth.instance.currentUser!.delete(); //clean up - return; - } catch (e) { - fail('should have thrown an FirebaseAuthException'); - } + User currentUser = FirebaseAuth.instance.currentUser!; + expect(currentUser.email, equals(email)); + expect(currentUser.uid, equals(initialUser.uid)); + }); - fail('should have thrown an error'); - }); + test('should throw user-mismatch ', () async { + // Setup + String emailAlready = generateRandomEmail(); - test('should throw user-not-found or user-mismatch ', () async { - // Setup - UserCredential userCredential = - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: testPassword, - ); - User user = userCredential.user!; + await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: email, + password: testPassword, + ); - try { - // Test - AuthCredential credential = EmailAuthProvider.credential( - email: 'userdoesnotexist@foobar.com', + await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: emailAlready, password: testPassword, ); - await user.reauthenticateWithCredential(credential); - } on FirebaseAuthException catch (e) { - // Platforms throw different errors. For now, leave them as is - // but in future we might want to edit them before sending to user. - if (e.code != 'user-mismatch' && e.code != 'user-not-found') { - fail('should have thrown a valid error code (got ${e.code}'); + + try { + // Test + AuthCredential credential = EmailAuthProvider.credential( + email: email, + password: testPassword, + ); + await FirebaseAuth.instance.currentUser! + .reauthenticateWithCredential(credential); + } on FirebaseAuthException catch (e) { + // Assertions + expect(e.code, equals('user-mismatch')); + expect( + e.message, + equals( + 'The supplied credentials do not correspond to the previously signed in user.', + ), + ); + await FirebaseAuth.instance.currentUser!.delete(); //clean up + return; + } catch (e) { + fail('should have thrown an FirebaseAuthException'); } - return; - } catch (e) { - fail('should have thrown an FirebaseAuthException'); - } + fail('should have thrown an error'); + }); - fail('should have thrown an error'); - }); + test('should throw user-not-found or user-mismatch ', () async { + // Setup + UserCredential userCredential = + await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: email, + password: testPassword, + ); + User user = userCredential.user!; - // TODO error codes no longer match when using emulator. - // test('should throw invalid-email ', () async { - // // Setup - // await FirebaseAuth.instance.createUserWithEmailAndPassword( - // email: email, password: testPassword); - // - // try { - // // Test - // AuthCredential credential = EmailAuthProvider.credential( - // email: 'invalid', password: testPassword); - // await FirebaseAuth.instance.currentUser - // .reauthenticateWithCredential(credential); - // } on FirebaseAuthException catch (e) { - // // Assertions - // expect(e.code, equals('invalid-email')); - // expect(e.message, equals('The email address is badly formatted.')); - // return; - // } catch (e) { - // fail('should have thrown an FirebaseAuthException'); - // } - // - // fail('should have thrown an error'); - // }); + try { + // Test + AuthCredential credential = EmailAuthProvider.credential( + email: 'userdoesnotexist@foobar.com', + password: testPassword, + ); + await user.reauthenticateWithCredential(credential); + } on FirebaseAuthException catch (e) { + // Platforms throw different errors. For now, leave them as is + // but in future we might want to edit them before sending to user. + if (e.code != 'user-mismatch' && e.code != 'user-not-found') { + fail('should have thrown a valid error code (got ${e.code}'); + } - test('should throw wrong-password ', () async { - // Setup - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: testPassword, - ); + return; + } catch (e) { + fail('should have thrown an FirebaseAuthException'); + } - try { - // Test - AuthCredential credential = EmailAuthProvider.credential( + fail('should have thrown an error'); + }); + + // TODO error codes no longer match when using emulator. + // test('should throw invalid-email ', () async { + // // Setup + // await FirebaseAuth.instance.createUserWithEmailAndPassword( + // email: email, password: testPassword); + // + // try { + // // Test + // AuthCredential credential = EmailAuthProvider.credential( + // email: 'invalid', password: testPassword); + // await FirebaseAuth.instance.currentUser + // .reauthenticateWithCredential(credential); + // } on FirebaseAuthException catch (e) { + // // Assertions + // expect(e.code, equals('invalid-email')); + // expect(e.message, equals('The email address is badly formatted.')); + // return; + // } catch (e) { + // fail('should have thrown an FirebaseAuthException'); + // } + // + // fail('should have thrown an error'); + // }); + + test('should throw wrong-password ', () async { + // Setup + await FirebaseAuth.instance.createUserWithEmailAndPassword( email: email, - password: 'WRONG_testPassword', - ); - await FirebaseAuth.instance.currentUser! - .reauthenticateWithCredential(credential); - } on FirebaseAuthException catch (e) { - // Assertions - expect(e.code, equals('wrong-password')); - expect( - e.message, - equals( - 'The password is invalid or the user does not have a password.', - ), + password: testPassword, ); - return; - } catch (e) { - fail('should have thrown an FirebaseAuthException'); - } - fail('should have thrown an error'); - }); - }); + try { + // Test + AuthCredential credential = EmailAuthProvider.credential( + email: email, + password: 'WRONG_testPassword', + ); + await FirebaseAuth.instance.currentUser! + .reauthenticateWithCredential(credential); + } on FirebaseAuthException catch (e) { + // Assertions + expect(e.code, equals('wrong-password')); + expect( + e.message, + equals( + 'The password is invalid or the user does not have a password.', + ), + ); + return; + } catch (e) { + fail('should have thrown an FirebaseAuthException'); + } - group('reload()', () { - test('should not error', () async { - await FirebaseAuth.instance.signInAnonymously(); - try { - await FirebaseAuth.instance.currentUser!.reload(); - await FirebaseAuth.instance.signOut(); - } catch (e) { - fail('should not throw error'); - } - expect(FirebaseAuth.instance.currentUser, isNull); + fail('should have thrown an error'); + }); }); - }); - group('sendEmailVerification()', () { - test('should not error', () async { - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: generateRandomEmail(), - password: testPassword, - ); - try { - await FirebaseAuth.instance.currentUser!.sendEmailVerification(); - } catch (e) { - fail('should not throw error'); - } - expect(FirebaseAuth.instance.currentUser, isNotNull); + group('reload()', () { + test('should not error', () async { + await FirebaseAuth.instance.signInAnonymously(); + try { + await FirebaseAuth.instance.currentUser!.reload(); + await FirebaseAuth.instance.signOut(); + } catch (e) { + fail('should not throw error'); + } + expect(FirebaseAuth.instance.currentUser, isNull); + }); }); - test( - 'should work with actionCodeSettings', - () async { - // Setup - ActionCodeSettings actionCodeSettings = ActionCodeSettings( - handleCodeInApp: true, - url: 'https://flutterfire-e2e-tests.firebaseapp.com/foo', - ); + group('sendEmailVerification()', () { + test('should not error', () async { await FirebaseAuth.instance.createUserWithEmailAndPassword( email: generateRandomEmail(), password: testPassword, ); - - // Test try { - await FirebaseAuth.instance.currentUser! - .sendEmailVerification(actionCodeSettings); - } catch (error) { - fail('$error'); + await FirebaseAuth.instance.currentUser!.sendEmailVerification(); + } catch (e) { + fail('should not throw error'); } expect(FirebaseAuth.instance.currentUser, isNotNull); - }, - // macOS skipped because it needs keychain sharing entitlement. See: https://github.com/firebase/flutterfire/issues/9538 - skip: kIsWeb || defaultTargetPlatform == TargetPlatform.macOS, - ); - }); - - group('unlink()', () { - test('should unlink the email address', () async { - // Setup - await FirebaseAuth.instance.signInAnonymously(); - - AuthCredential credential = - EmailAuthProvider.credential(email: email, password: testPassword); - await FirebaseAuth.instance.currentUser!.linkWithCredential(credential); - - // verify user is linked - User linkedUser = FirebaseAuth.instance.currentUser!; - expect(linkedUser.email, email); - expect(linkedUser.providerData, isA>()); - expect(linkedUser.providerData.length, equals(1)); - - // Test - await FirebaseAuth.instance.currentUser! - .unlink(EmailAuthProvider.PROVIDER_ID); - - // Assertions - User unlinkedUser = FirebaseAuth.instance.currentUser!; - expect(unlinkedUser.providerData, isA>()); - expect(unlinkedUser.providerData.length, equals(0)); - }); + }); - test('should throw error if provider id given does not exist', () async { - // Setup - await FirebaseAuth.instance.signInAnonymously(); + test( + 'should work with actionCodeSettings', + () async { + // Setup + ActionCodeSettings actionCodeSettings = ActionCodeSettings( + handleCodeInApp: true, + url: 'https://flutterfire-e2e-tests.firebaseapp.com/foo', + ); + await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: generateRandomEmail(), + password: testPassword, + ); - AuthCredential credential = - EmailAuthProvider.credential(email: email, password: testPassword); - await FirebaseAuth.instance.currentUser!.linkWithCredential(credential); + // Test + try { + await FirebaseAuth.instance.currentUser! + .sendEmailVerification(actionCodeSettings); + } catch (error) { + fail('$error'); + } + expect(FirebaseAuth.instance.currentUser, isNotNull); + }, + // macOS skipped because it needs keychain sharing entitlement. See: https://github.com/firebase/flutterfire/issues/9538 + skip: kIsWeb || defaultTargetPlatform == TargetPlatform.macOS, + ); + }); - // verify user is linked - User linkedUser = FirebaseAuth.instance.currentUser!; - expect(linkedUser.email, email); + group('unlink()', () { + test('should unlink the email address', () async { + // Setup + await FirebaseAuth.instance.signInAnonymously(); - // Test - try { - await FirebaseAuth.instance.currentUser!.unlink('invalid'); - } on FirebaseAuthException catch (e) { - expect(e.code, 'no-such-provider'); - expect( - e.message, - 'User was not linked to an account with the given provider.', - ); - return; - } catch (e) { - fail('should have thrown an FirebaseAuthException error'); - } - fail('should have thrown an error'); - }); + AuthCredential credential = EmailAuthProvider.credential( + email: email, + password: testPassword, + ); + await FirebaseAuth.instance.currentUser! + .linkWithCredential(credential); - test('should throw error if user does not have this provider linked', - () async { - // Setup - await FirebaseAuth.instance.signInAnonymously(); - // Test - try { + // verify user is linked + User linkedUser = FirebaseAuth.instance.currentUser!; + expect(linkedUser.email, email); + expect(linkedUser.providerData, isA>()); + expect(linkedUser.providerData.length, equals(1)); + + // Test await FirebaseAuth.instance.currentUser! .unlink(EmailAuthProvider.PROVIDER_ID); - } on FirebaseAuthException catch (e) { - expect(e.code, 'no-such-provider'); - expect( - e.message, - 'User was not linked to an account with the given provider.', - ); - return; - } catch (e) { - fail('should have thrown an FirebaseAuthException error'); - } - fail('should have thrown an error'); - }); - }); - - group('updateEmail()', () { - test('should update the email address', () async { - String emailBefore = generateRandomEmail(); - // Setup - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: emailBefore, - password: testPassword, - ); - expect(FirebaseAuth.instance.currentUser!.email, equals(emailBefore)); - // Update user email - await FirebaseAuth.instance.currentUser!.updateEmail(email); - expect(FirebaseAuth.instance.currentUser!.email, equals(email)); - }); - }); + // Assertions + User unlinkedUser = FirebaseAuth.instance.currentUser!; + expect(unlinkedUser.providerData, isA>()); + expect(unlinkedUser.providerData.length, equals(0)); + }); - group('updatePassword()', () { - test('should update the password', () async { - String pass = '${testPassword}1'; - String pass2 = '${testPassword}2'; - // Setup - await FirebaseAuth.instance - .createUserWithEmailAndPassword(email: email, password: pass); + test('should throw error if provider id given does not exist', + () async { + // Setup + await FirebaseAuth.instance.signInAnonymously(); - // Update user password - await FirebaseAuth.instance.currentUser!.updatePassword(pass2); + AuthCredential credential = EmailAuthProvider.credential( + email: email, + password: testPassword, + ); + await FirebaseAuth.instance.currentUser! + .linkWithCredential(credential); - // // Sign out - await FirebaseAuth.instance.signOut(); + // verify user is linked + User linkedUser = FirebaseAuth.instance.currentUser!; + expect(linkedUser.email, email); - // Log in with the new password - await FirebaseAuth.instance - .signInWithEmailAndPassword(email: email, password: pass2); + // Test + try { + await FirebaseAuth.instance.currentUser!.unlink('invalid'); + } on FirebaseAuthException catch (e) { + expect(e.code, 'no-such-provider'); + expect( + e.message, + 'User was not linked to an account with the given provider.', + ); + return; + } catch (e) { + fail('should have thrown an FirebaseAuthException error'); + } + fail('should have thrown an error'); + }); - // Assertions - expect(FirebaseAuth.instance.currentUser, isA()); - expect(FirebaseAuth.instance.currentUser!.email, equals(email)); + test('should throw error if user does not have this provider linked', + () async { + // Setup + await FirebaseAuth.instance.signInAnonymously(); + // Test + try { + await FirebaseAuth.instance.currentUser! + .unlink(EmailAuthProvider.PROVIDER_ID); + } on FirebaseAuthException catch (e) { + expect(e.code, 'no-such-provider'); + expect( + e.message, + 'User was not linked to an account with the given provider.', + ); + return; + } catch (e) { + fail('should have thrown an FirebaseAuthException error'); + } + fail('should have thrown an error'); + }); }); - test('should throw error if password is weak', () async { - // Setup - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: testPassword, - ); - // Test - try { - // Update user password - await FirebaseAuth.instance.currentUser!.updatePassword('weak'); - } on FirebaseAuthException catch (e) { - expect(e.code, 'weak-password'); - expect(e.message, 'Password should be at least 6 characters'); - return; - } catch (e) { - fail('should have thrown an FirebaseAuthException error'); - } - fail('should have thrown an error'); + group('updateEmail()', () { + test('should update the email address', () async { + String emailBefore = generateRandomEmail(); + // Setup + await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: emailBefore, + password: testPassword, + ); + expect(FirebaseAuth.instance.currentUser!.email, equals(emailBefore)); + + // Update user email + await FirebaseAuth.instance.currentUser!.updateEmail(email); + expect(FirebaseAuth.instance.currentUser!.email, equals(email)); + }); }); - }); - group('refreshToken', () { - test( - 'should throw an unsupported error on non web platforms', - () async { + group('updatePassword()', () { + test('should update the password', () async { + String pass = '${testPassword}1'; + String pass2 = '${testPassword}2'; // Setup - await FirebaseAuth.instance.signInAnonymously(); + await FirebaseAuth.instance + .createUserWithEmailAndPassword(email: email, password: pass); - // Test - FirebaseAuth.instance.currentUser!.refreshToken; + // Update user password + await FirebaseAuth.instance.currentUser!.updatePassword(pass2); - // Assertions - expect( - FirebaseAuth.instance.currentUser!.refreshToken, - isA(), - ); - expect(FirebaseAuth.instance.currentUser!.refreshToken, equals('')); - }, - // macOS skipped because it needs keychain sharing entitlement. See: https://github.com/firebase/flutterfire/issues/9538 - skip: kIsWeb || defaultTargetPlatform == TargetPlatform.macOS, - ); - - test( - 'should return a token on web', - () async { - // Setup - await FirebaseAuth.instance.signInAnonymously(); + // // Sign out + await FirebaseAuth.instance.signOut(); - // Test - FirebaseAuth.instance.currentUser!.refreshToken; + // Log in with the new password + await FirebaseAuth.instance + .signInWithEmailAndPassword(email: email, password: pass2); // Assertions - expect( - FirebaseAuth.instance.currentUser!.refreshToken, - isA(), - ); - expect( - FirebaseAuth.instance.currentUser!.refreshToken!.isEmpty, - isFalse, + expect(FirebaseAuth.instance.currentUser, isA()); + expect(FirebaseAuth.instance.currentUser!.email, equals(email)); + }); + test('should throw error if password is weak', () async { + // Setup + await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: email, + password: testPassword, ); - }, - skip: !kIsWeb, - ); - }); - group('user.metadata', () { - test( - "should have the properties 'lastSignInTime' & 'creationTime' which are ISO strings", + // Test + try { + // Update user password + await FirebaseAuth.instance.currentUser!.updatePassword('weak'); + } on FirebaseAuthException catch (e) { + expect(e.code, 'weak-password'); + expect(e.message, 'Password should be at least 6 characters'); + return; + } catch (e) { + fail('should have thrown an FirebaseAuthException error'); + } + fail('should have thrown an error'); + }); + }); + + group('refreshToken', () { + test( + 'should throw an unsupported error on non web platforms', () async { - // Setup - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: generateRandomEmail(), - password: testPassword, - ); - User user = FirebaseAuth.instance.currentUser!; + // Setup + await FirebaseAuth.instance.signInAnonymously(); - // Test - UserMetadata metadata = user.metadata; + // Test + FirebaseAuth.instance.currentUser!.refreshToken; - // Assertions - expect(metadata.lastSignInTime, isA()); - expect(metadata.lastSignInTime!.year, DateTime.now().year); - expect(metadata.creationTime, isA()); - expect(metadata.creationTime!.year, DateTime.now().year); - }); - }); + // Assertions + expect( + FirebaseAuth.instance.currentUser!.refreshToken, + isNull, + ); + }, + // macOS skipped because it needs keychain sharing entitlement. See: https://github.com/firebase/flutterfire/issues/9538 + // iOS supports it + skip: kIsWeb || + defaultTargetPlatform == TargetPlatform.macOS || + defaultTargetPlatform == TargetPlatform.iOS, + ); - group('updateDisplayName', () { - test('updates the user displayName without impacting the photoURL', + test( + 'should return a token on web', () async { - // First create a user with a photo - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: testPassword, - ); - await FirebaseAuth.instance.currentUser!.updateDisplayName('Mona Lisa'); - await FirebaseAuth.instance.currentUser!.updatePhotoURL( - 'http://photo.url/test.jpg', - ); - await FirebaseAuth.instance.currentUser!.reload(); + // Setup + await FirebaseAuth.instance.signInAnonymously(); - expect( - FirebaseAuth.instance.currentUser!.photoURL, - 'http://photo.url/test.jpg', - ); - expect( - FirebaseAuth.instance.currentUser!.displayName, - 'Mona Lisa', + // Test + FirebaseAuth.instance.currentUser!.refreshToken; + + // Assertions + expect( + FirebaseAuth.instance.currentUser!.refreshToken, + isA(), + ); + expect( + FirebaseAuth.instance.currentUser!.refreshToken!.isEmpty, + isFalse, + ); + }, + skip: !kIsWeb, ); + }); + + group('user.metadata', () { + test( + "should have the properties 'lastSignInTime' & 'creationTime' which are ISO strings", + () async { + // Setup + await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: generateRandomEmail(), + password: testPassword, + ); + User user = FirebaseAuth.instance.currentUser!; - await FirebaseAuth.instance.currentUser! - .updateDisplayName('John Smith'); - await FirebaseAuth.instance.currentUser!.reload(); + // Test + UserMetadata metadata = user.metadata; - expect( - FirebaseAuth.instance.currentUser!.photoURL, - 'http://photo.url/test.jpg', - ); - expect( - FirebaseAuth.instance.currentUser!.displayName, - 'John Smith', - ); + // Assertions + expect(metadata.lastSignInTime, isA()); + expect(metadata.lastSignInTime!.year, DateTime.now().year); + expect(metadata.creationTime, isA()); + expect(metadata.creationTime!.year, DateTime.now().year); + }); }); - test( - 'can set the displayName to null', - () async { + group('updateDisplayName', () { + test('updates the user displayName without impacting the photoURL', + () async { // First create a user with a photo await FirebaseAuth.instance.createUserWithEmailAndPassword( email: email, @@ -690,321 +668,331 @@ void main() { ); await FirebaseAuth.instance.currentUser! .updateDisplayName('Mona Lisa'); + await FirebaseAuth.instance.currentUser!.updatePhotoURL( + 'http://photo.url/test.jpg', + ); await FirebaseAuth.instance.currentUser!.reload(); - // Just checking that the user indeed had a name before we set it to null + expect( + FirebaseAuth.instance.currentUser!.photoURL, + 'http://photo.url/test.jpg', + ); expect( FirebaseAuth.instance.currentUser!.displayName, - isNotNull, + 'Mona Lisa', ); - await FirebaseAuth.instance.currentUser!.updateDisplayName(null); + await FirebaseAuth.instance.currentUser! + .updateDisplayName('John Smith'); await FirebaseAuth.instance.currentUser!.reload(); expect( - FirebaseAuth.instance.currentUser!.displayName, - isNull, - ); - // Skip apple CI because of https://github.com/firebase/firebase-ios-sdk/issues/8149 - // Using `kIsWeb` because `Platform` is not available on web - }, - // setting `displayName` on web throws an error - skip: kIsWeb || - (defaultTargetPlatform == TargetPlatform.iOS || - defaultTargetPlatform == TargetPlatform.macOS), - ); - }); - - group('updatePhotoURL', () { - test('updates the photoURL without impacting the displayName', () async { - // First create a user with a photo - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: testPassword, - ); - await Future.wait([ - FirebaseAuth.instance.currentUser!.updateDisplayName('Mona Lisa'), - FirebaseAuth.instance.currentUser!.updatePhotoURL( + FirebaseAuth.instance.currentUser!.photoURL, 'http://photo.url/test.jpg', - ), - ]); - await FirebaseAuth.instance.currentUser!.reload(); + ); + expect( + FirebaseAuth.instance.currentUser!.displayName, + 'John Smith', + ); + }); - expect( - FirebaseAuth.instance.currentUser!.photoURL, - 'http://photo.url/test.jpg', - ); - expect( - FirebaseAuth.instance.currentUser!.displayName, - 'Mona Lisa', - ); + test( + 'can set the displayName to null', + () async { + // First create a user with a photo + await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: email, + password: testPassword, + ); + await FirebaseAuth.instance.currentUser! + .updateDisplayName('Mona Lisa'); + await FirebaseAuth.instance.currentUser!.reload(); - await FirebaseAuth.instance.currentUser!.updatePhotoURL( - 'http://photo.url/dash.jpg', - ); - await FirebaseAuth.instance.currentUser!.reload(); + // Just checking that the user indeed had a name before we set it to null + expect( + FirebaseAuth.instance.currentUser!.displayName, + isNotNull, + ); - expect( - FirebaseAuth.instance.currentUser!.photoURL, - 'http://photo.url/dash.jpg', - ); - expect( - FirebaseAuth.instance.currentUser!.displayName, - 'Mona Lisa', + await FirebaseAuth.instance.currentUser!.updateDisplayName(null); + await FirebaseAuth.instance.currentUser!.reload(); + + expect( + FirebaseAuth.instance.currentUser!.displayName, + isNull, + ); + // Skip apple CI because of https://github.com/firebase/firebase-ios-sdk/issues/8149 + // Using `kIsWeb` because `Platform` is not available on web + }, + // setting `displayName` on web throws an error + skip: kIsWeb || + (defaultTargetPlatform == TargetPlatform.iOS || + defaultTargetPlatform == TargetPlatform.macOS), ); }); - test( - 'can set the photoURL to null', - () async { + group('updatePhotoURL', () { + test('updates the photoURL without impacting the displayName', + () async { // First create a user with a photo await FirebaseAuth.instance.createUserWithEmailAndPassword( email: email, password: testPassword, ); - await FirebaseAuth.instance.currentUser!.updatePhotoURL( - 'http://photo.url/test.jpg', - ); + await Future.wait([ + FirebaseAuth.instance.currentUser!.updateDisplayName('Mona Lisa'), + FirebaseAuth.instance.currentUser!.updatePhotoURL( + 'http://photo.url/test.jpg', + ), + ]); await FirebaseAuth.instance.currentUser!.reload(); - // Just checking that the user indeed had a photo before we set it to null expect( FirebaseAuth.instance.currentUser!.photoURL, - isNotNull, + 'http://photo.url/test.jpg', + ); + expect( + FirebaseAuth.instance.currentUser!.displayName, + 'Mona Lisa', ); - await FirebaseAuth.instance.currentUser!.updatePhotoURL(null); + await FirebaseAuth.instance.currentUser!.updatePhotoURL( + 'http://photo.url/dash.jpg', + ); await FirebaseAuth.instance.currentUser!.reload(); expect( FirebaseAuth.instance.currentUser!.photoURL, - isNull, - ); - }, - // setting `photoURL` on web throws an error - // macOS skipped because it needs keychain sharing entitlement. See: https://github.com/firebase/flutterfire/issues/9538 - skip: kIsWeb || defaultTargetPlatform == TargetPlatform.macOS, - ); - }); - - group('updateProfile()', () { - test('should update the profile', () async { - String displayName = 'testName'; - String photoURL = 'http://photo.url/test.jpg'; - - // Setup - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: testPassword, - ); - - // Update user profile - // ignore: deprecated_member_use - await FirebaseAuth.instance.currentUser!.updateProfile( - displayName: displayName, - photoURL: photoURL, - ); - - await FirebaseAuth.instance.currentUser!.reload(); - User user = FirebaseAuth.instance.currentUser!; - - // Assertions - expect(user, isA()); - expect(user.email, email); - expect(user.displayName, equals(displayName)); - expect(user.photoURL, equals(photoURL)); - }); - }); - - group('updatePhoneNumber()', () { - // TODO this test is now flakey since switching to Auth emulator, consider - // rewriting it. - // test('should update the phone number', () async { - // // Setup - // await FirebaseAuth.instance.signInAnonymously(); - // - // Future getVerificationId() { - // Completer completer = Completer(); - // - // unawaited(FirebaseAuth.instance.verifyPhoneNumber( - // phoneNumber: testPhoneNumber, - // verificationCompleted: (PhoneAuthCredential credential) { - // fail('Should not have auto resolved'); - // }, - // verificationFailed: (FirebaseException e) { - // fail('Should not have errored'); - // }, - // codeSent: (String verificationId, int resetToken) { - // completer.complete(verificationId); - // }, - // codeAutoRetrievalTimeout: (String foo) {}, - // )); - // - // return completer.future; - // } - // - // String storedVerificationId = await getVerificationId(); - // - // // Update user profile - // await FirebaseAuth.instance.currentUser - // .updatePhoneNumber(PhoneAuthProvider.credential( - // verificationId: storedVerificationId, - // smsCode: await emulatorPhoneVerificationCode(testPhoneNumber), - // )); - // - // await FirebaseAuth.instance.currentUser.reload(); - // User user = FirebaseAuth.instance.currentUser; - // - // // Assertions - // expect(user, isA()); - // expect(user.phoneNumber, equals(testPhoneNumber)); - // }, skip: kIsWeb || defaultTargetPlatform == TargetPlatform.macOS); - - test( - 'should throw an FirebaseAuthException if verification id is invalid', - () async { - // Setup - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: testPassword, + 'http://photo.url/dash.jpg', ); + expect( + FirebaseAuth.instance.currentUser!.displayName, + 'Mona Lisa', + ); + }); - try { - // Update user profile - await FirebaseAuth.instance.currentUser!.updatePhoneNumber( - PhoneAuthProvider.credential( - verificationId: 'invalid', - smsCode: '123456', - ), + test( + 'can set the photoURL to null', + () async { + // First create a user with a photo + await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: email, + password: testPassword, ); - } on FirebaseAuthException catch (e) { - expect(e.code, 'invalid-verification-id'); + await FirebaseAuth.instance.currentUser!.updatePhotoURL( + 'http://photo.url/test.jpg', + ); + await FirebaseAuth.instance.currentUser!.reload(); + + // Just checking that the user indeed had a photo before we set it to null expect( - e.message, - 'The verification ID used to create the phone auth credential is invalid.', + FirebaseAuth.instance.currentUser!.photoURL, + isNotNull, ); - return; - } catch (e) { - fail('should have thrown a AssertionError error'); - } - fail('should have thrown an error'); - }, - skip: kIsWeb || defaultTargetPlatform == TargetPlatform.macOS, - ); + await FirebaseAuth.instance.currentUser!.updatePhotoURL(null); + await FirebaseAuth.instance.currentUser!.reload(); - // TODO error codes no longer match up on emulator - // test('should throw an error when verification id is an empty string', - // () async { - // // Setup - // await FirebaseAuth.instance.createUserWithEmailAndPassword( - // email: email, password: testPassword); - // - // try { - // // Test - // await FirebaseAuth.instance.currentUser.updatePhoneNumber( - // PhoneAuthProvider.credential( - // verificationId: '', smsCode: '123456')); - // } on FirebaseAuthException catch (e) { - // expect(e.code, 'invalid-verification-id'); - // expect(e.message, - // 'The verification ID used to create the phone auth credential is invalid.'); - // return; - // } catch (e) { - // fail('should have thrown an FirebaseAuthException error'); - // } - // - // fail('should have thrown an error'); - // }, skip: kIsWeb || defaultTargetPlatform == TargetPlatform.macOS); - }); - - // TODO fails on emulator but works on live Firebase project - // group('verifyBeforeUpdateEmail()', () { - // test( - // 'should send verification email', - // () async { - // await ensureSignedIn(testEmail); - // await FirebaseAuth.instance.currentUser.verifyBeforeUpdateEmail( - // 'updated-test-email@example.com', - // ActionCodeSettings( - // url: 'http://action-code-test.com', - // handleCodeInApp: true, - // )); - // - // // Confirm with the Auth emulator that it triggered an email sending code. - // final oobCode = await emulatorOutOfBandCode( - // email, EmulatorOobCodeType.verifyEmail); - // expect(oobCode, isNotNull); - // expect(oobCode.email, testEmail); - // expect(oobCode.type, EmulatorOobCodeType.verifyEmail); - // }, - // ); - // }); - - group('delete()', () { - test('should delete a user', () async { - // Setup - late User user; - UserCredential userCredential; - - userCredential = - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: testPassword, + expect( + FirebaseAuth.instance.currentUser!.photoURL, + isNull, + ); + }, + // setting `photoURL` on web throws an error + // macOS skipped because it needs keychain sharing entitlement. See: https://github.com/firebase/flutterfire/issues/9538 + skip: kIsWeb || defaultTargetPlatform == TargetPlatform.macOS, ); - user = userCredential.user!; - - // Test - await user.delete(); - - // Assertions - expect(FirebaseAuth.instance.currentUser, equals(null)); - await FirebaseAuth.instance - .createUserWithEmailAndPassword( - email: email, - password: testPassword, - ) - .then((UserCredential userCredential) { - expect(FirebaseAuth.instance.currentUser!.email, equals(email)); - return; - }).catchError((Object error) { - fail('Should have successfully created user after deletion'); - }); }); - test('should throw an error on delete when no user is signed in', + group('updatePhoneNumber()', () { + // TODO this test is now flakey since switching to Auth emulator, consider + // rewriting it. + // test('should update the phone number', () async { + // // Setup + // await FirebaseAuth.instance.signInAnonymously(); + // + // Future getVerificationId() { + // Completer completer = Completer(); + // + // unawaited(FirebaseAuth.instance.verifyPhoneNumber( + // phoneNumber: testPhoneNumber, + // verificationCompleted: (PhoneAuthCredential credential) { + // fail('Should not have auto resolved'); + // }, + // verificationFailed: (FirebaseException e) { + // fail('Should not have errored'); + // }, + // codeSent: (String verificationId, int resetToken) { + // completer.complete(verificationId); + // }, + // codeAutoRetrievalTimeout: (String foo) {}, + // )); + // + // return completer.future; + // } + // + // String storedVerificationId = await getVerificationId(); + // + // // Update user profile + // await FirebaseAuth.instance.currentUser + // .updatePhoneNumber(PhoneAuthProvider.credential( + // verificationId: storedVerificationId, + // smsCode: await emulatorPhoneVerificationCode(testPhoneNumber), + // )); + // + // await FirebaseAuth.instance.currentUser.reload(); + // User user = FirebaseAuth.instance.currentUser; + // + // // Assertions + // expect(user, isA()); + // expect(user.phoneNumber, equals(testPhoneNumber)); + // }, skip: kIsWeb || defaultTargetPlatform == TargetPlatform.macOS); + + test( + 'should throw an FirebaseAuthException if verification id is invalid', () async { - // Setup - late User user; - UserCredential userCredential; - - userCredential = + // Setup await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: testPassword, + email: email, + password: testPassword, + ); + + try { + // Update user profile + await FirebaseAuth.instance.currentUser!.updatePhoneNumber( + PhoneAuthProvider.credential( + verificationId: 'invalid', + smsCode: '123456', + ), + ); + } on FirebaseAuthException catch (e) { + expect(e.code, 'invalid-verification-id'); + expect( + e.message, + 'The verification ID used to create the phone auth credential is invalid.', + ); + return; + } catch (e) { + fail('should have thrown a AssertionError error'); + } + + fail('should have thrown an error'); + }, + skip: kIsWeb || defaultTargetPlatform == TargetPlatform.macOS, ); - user = userCredential.user!; - await FirebaseAuth.instance.signOut(); + // TODO error codes no longer match up on emulator + // test('should throw an error when verification id is an empty string', + // () async { + // // Setup + // await FirebaseAuth.instance.createUserWithEmailAndPassword( + // email: email, password: testPassword); + // + // try { + // // Test + // await FirebaseAuth.instance.currentUser.updatePhoneNumber( + // PhoneAuthProvider.credential( + // verificationId: '', smsCode: '123456')); + // } on FirebaseAuthException catch (e) { + // expect(e.code, 'invalid-verification-id'); + // expect(e.message, + // 'The verification ID used to create the phone auth credential is invalid.'); + // return; + // } catch (e) { + // fail('should have thrown an FirebaseAuthException error'); + // } + // + // fail('should have thrown an error'); + // }, skip: kIsWeb || defaultTargetPlatform == TargetPlatform.macOS); + }); + + // TODO fails on emulator but works on live Firebase project + // group('verifyBeforeUpdateEmail()', () { + // test( + // 'should send verification email', + // () async { + // await ensureSignedIn(testEmail); + // await FirebaseAuth.instance.currentUser.verifyBeforeUpdateEmail( + // 'updated-test-email@example.com', + // ActionCodeSettings( + // url: 'http://action-code-test.com', + // handleCodeInApp: true, + // )); + // + // // Confirm with the Auth emulator that it triggered an email sending code. + // final oobCode = await emulatorOutOfBandCode( + // email, EmulatorOobCodeType.verifyEmail); + // expect(oobCode, isNotNull); + // expect(oobCode.email, testEmail); + // expect(oobCode.type, EmulatorOobCodeType.verifyEmail); + // }, + // ); + // }); + + group('delete()', () { + test('should delete a user', () async { + // Setup + late User user; + UserCredential userCredential; + + userCredential = + await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: email, + password: testPassword, + ); + user = userCredential.user!; - try { // Test await user.delete(); - } on FirebaseAuthException catch (e) { + // Assertions - expect(e.code, 'no-current-user'); - expect(e.message, 'No user currently signed in.'); + expect(FirebaseAuth.instance.currentUser, equals(null)); + await FirebaseAuth.instance + .createUserWithEmailAndPassword( + email: email, + password: testPassword, + ) + .then((UserCredential userCredential) { + expect(FirebaseAuth.instance.currentUser!.email, equals(email)); + return; + }).catchError((Object error) { + fail('Should have successfully created user after deletion'); + }); + }); - return; - } catch (e) { - fail('Should have thrown an FirebaseAuthException error'); - } + test('should throw an error on delete when no user is signed in', + () async { + // Setup + late User user; + UserCredential userCredential; - fail('Should have thrown an error'); + userCredential = + await FirebaseAuth.instance.createUserWithEmailAndPassword( + email: email, + password: testPassword, + ); + user = userCredential.user!; + + await FirebaseAuth.instance.signOut(); + + try { + // Test + await user.delete(); + } on FirebaseAuthException catch (e) { + // Assertions + expect(e.code, 'no-current-user'); + expect(e.message, 'No user currently signed in.'); + + return; + } catch (e) { + fail('Should have thrown an FirebaseAuthException error'); + } + + fail('Should have thrown an error'); + }); }); - }); - }, - // macOS skipped because it needs keychain sharing entitlement. See: https://github.com/firebase/flutterfire/issues/9538 - skip: defaultTargetPlatform == TargetPlatform.macOS, + }, + // macOS skipped because it needs keychain sharing entitlement. See: https://github.com/firebase/flutterfire/issues/9538 + skip: defaultTargetPlatform == TargetPlatform.macOS, ); } diff --git a/tests/ios/Runner.xcodeproj/project.pbxproj b/tests/ios/Runner.xcodeproj/project.pbxproj index 3b108edf1bb6..f968b10e8daf 100644 --- a/tests/ios/Runner.xcodeproj/project.pbxproj +++ b/tests/ios/Runner.xcodeproj/project.pbxproj @@ -207,6 +207,7 @@ files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -391,7 +392,7 @@ PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.firebase.tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; + SWIFT_VERSION = 5.6; VERSIONING_SYSTEM = "apple-generic"; }; name = Profile; @@ -522,7 +523,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; + SWIFT_VERSION = 5.6; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -545,7 +546,7 @@ PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.firebase.tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; + SWIFT_VERSION = 5.6; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; diff --git a/tests/macos/Runner.xcodeproj/project.pbxproj b/tests/macos/Runner.xcodeproj/project.pbxproj index 7ae45b4240bb..31e1da0d4fbb 100644 --- a/tests/macos/Runner.xcodeproj/project.pbxproj +++ b/tests/macos/Runner.xcodeproj/project.pbxproj @@ -450,7 +450,7 @@ "@executable_path/../Frameworks", ); PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 5.0; + SWIFT_VERSION = 5.6; }; name = Profile; }; @@ -580,7 +580,7 @@ ); PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; + SWIFT_VERSION = 5.6; }; name = Debug; }; @@ -601,7 +601,7 @@ "@executable_path/../Frameworks", ); PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 5.0; + SWIFT_VERSION = 5.6; }; name = Release; };