diff --git a/packages/auth/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java b/packages/auth/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java index 6e4decbf..f5af96c2 100644 --- a/packages/auth/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java +++ b/packages/auth/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java @@ -1910,28 +1910,36 @@ class ReactNativeFirebaseAuthModule extends ReactNativeFirebaseModule { private ActionCodeSettings buildActionCodeSettings(ReadableMap actionCodeSettings) { ActionCodeSettings.Builder builder = ActionCodeSettings.newBuilder(); - ReadableMap android = actionCodeSettings.getMap("android"); - ReadableMap ios = actionCodeSettings.getMap("iOS"); + + // Required String url = actionCodeSettings.getString("url"); - if (android != null) { - boolean installApp = android.hasKey("installApp") && android.getBoolean("installApp"); + builder = builder.setUrl(Objects.requireNonNull(url)); + + if (actionCodeSettings.hasKey("handleCodeInApp")) { + builder = builder.setHandleCodeInApp(actionCodeSettings.getBoolean("handleCodeInApp")); + } + + if (actionCodeSettings.hasKey("dynamicLinkDomain")) { + builder = builder.setDynamicLinkDomain(actionCodeSettings.getString("dynamicLinkDomain")); + } + + if (actionCodeSettings.hasKey("android")) { + ReadableMap android = actionCodeSettings.getMap("android"); + boolean installApp = Objects.requireNonNull(android).hasKey("installApp") && android.getBoolean("installApp"); String minimumVersion = android.hasKey("minimumVersion") ? android.getString("minimumVersion") : null; String packageName = android.getString("packageName"); + builder = builder.setAndroidPackageName( Objects.requireNonNull(packageName), installApp, minimumVersion ); } - if (actionCodeSettings.hasKey("handleCodeInApp")) { - builder = builder.setHandleCodeInApp(actionCodeSettings.getBoolean("handleCodeInApp")); - } - if (ios != null && ios.hasKey("bundleId")) { + + if (actionCodeSettings.hasKey("iOS")) { + ReadableMap ios = actionCodeSettings.getMap("iOS"); builder = builder.setIOSBundleId(Objects.requireNonNull(ios.getString("bundleId"))); } - if (url != null) { - builder = builder.setUrl(url); - } return builder.build(); } diff --git a/packages/auth/e2e/user.e2e.js b/packages/auth/e2e/user.e2e.js index 722b840e..46ebd84d 100644 --- a/packages/auth/e2e/user.e2e.js +++ b/packages/auth/e2e/user.e2e.js @@ -174,6 +174,34 @@ describe('auth().currentUser', () => { return Promise.resolve(); }); + + it('should work with actionCodeSettings', async () => { + const actionCodeSettings = { + handleCodeInApp: true, + url: 'https://react-native-firebase-testing.firebaseapp.com/foo', + }; + await Utils.sleep(3000); + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); + + try { + await firebase.auth().currentUser.sendEmailVerification(actionCodeSettings); + await firebase.auth().currentUser.delete(); + } catch (error) { + console.log(error); + // Reject + try { + await firebase.auth().currentUser.delete(); + } catch (_) { + /* do nothing */ + } + + return Promise.reject(new Error('sendEmailVerification(actionCodeSettings) caused an error')); + } + + return Promise.resolve(); + }); }); describe('unlink()', () => { diff --git a/packages/auth/ios/RNFBAuth/RNFBAuthModule.m b/packages/auth/ios/RNFBAuth/RNFBAuthModule.m index 13a265d0..d351aa46 100644 --- a/packages/auth/ios/RNFBAuth/RNFBAuthModule.m +++ b/packages/auth/ios/RNFBAuth/RNFBAuthModule.m @@ -42,6 +42,7 @@ static NSString *const keyMinVersion = @"minimumVersion"; static NSString *const constAppLanguage = @"APP_LANGUAGE"; static NSString *const constAppUser = @"APP_USER"; static NSString *const keyHandleCodeInApp = @"handleCodeInApp"; +static NSString *const keyDynamicLinkDomain = @"dynamicLinkDomain"; static NSString *const keyAdditionalUserInfo = @"additionalUserInfo"; static NSString *const AUTH_STATE_CHANGED_EVENT = @"auth_state_changed"; static NSString *const AUTH_ID_TOKEN_CHANGED_EVENT = @"auth_id_token_changed"; @@ -1132,31 +1133,32 @@ RCT_EXPORT_METHOD(verifyPasswordResetCode: } - (FIRActionCodeSettings *)buildActionCodeSettings:(NSDictionary *)actionCodeSettings { - NSString *url = actionCodeSettings[keyUrl]; - NSDictionary *ios = actionCodeSettings[keyIOS]; - NSDictionary *android = actionCodeSettings[keyAndroid]; - BOOL handleCodeInApp = [actionCodeSettings[keyHandleCodeInApp] boolValue]; - FIRActionCodeSettings *settings = [[FIRActionCodeSettings alloc] init]; - if (android) { - NSString *packageName = android[keyPackageName]; - NSString *minimumVersion = android[keyMinVersion]; - BOOL installApp = [android[keyInstallApp] boolValue]; + NSString *url = actionCodeSettings[keyUrl]; + [settings setURL:[NSURL URLWithString:url]]; - [settings setAndroidPackageName:packageName installIfNotAvailable:installApp minimumVersion:minimumVersion]; - } - - if (handleCodeInApp) { + if (actionCodeSettings[keyHandleCodeInApp]) { + BOOL handleCodeInApp = [actionCodeSettings[keyHandleCodeInApp] boolValue]; [settings setHandleCodeInApp:handleCodeInApp]; } - if (ios && ios[keyBundleId]) { - [settings setIOSBundleID:ios[keyBundleId]]; + if (actionCodeSettings[keyDynamicLinkDomain]) { + NSString *dynamicLinkDomain = [actionCodeSettings[keyDynamicLinkDomain] stringValue]; + [settings setDynamicLinkDomain:dynamicLinkDomain]; } - if (url) { - [settings setURL:[NSURL URLWithString:url]]; + if (actionCodeSettings[keyAndroid]) { + NSDictionary *android = actionCodeSettings[keyAndroid]; + NSString *packageName = android[keyPackageName]; + NSString *minimumVersion = android[keyMinVersion]; + BOOL installApp = [android[keyInstallApp] boolValue]; + [settings setAndroidPackageName:packageName installIfNotAvailable:installApp minimumVersion:minimumVersion]; + } + + if (actionCodeSettings[keyIOS]) { + NSDictionary *ios = actionCodeSettings[keyIOS]; + [settings setIOSBundleID:ios[keyBundleId]]; } return settings; diff --git a/packages/auth/lib/User.js b/packages/auth/lib/User.js index 15bc169a..04121ba3 100644 --- a/packages/auth/lib/User.js +++ b/packages/auth/lib/User.js @@ -15,6 +15,8 @@ * */ +import { isObject, isString } from '@react-native-firebase/common'; + export default class User { constructor(auth, user) { this._auth = auth; @@ -94,6 +96,14 @@ export default class User { } sendEmailVerification(actionCodeSettings) { + if (isObject(actionCodeSettings)) { + if (!isString(actionCodeSettings.url)) { + throw new Error( + "firebase.auth.User.sendEmailVerification(*) 'actionCodeSettings.url' expected a string value.", + ); + } + } + return this._auth.native.sendEmailVerification(actionCodeSettings).then(user => { this._auth._setUser(user); }); diff --git a/packages/auth/lib/index.d.ts b/packages/auth/lib/index.d.ts index 935ed7e5..dabed906 100644 --- a/packages/auth/lib/index.d.ts +++ b/packages/auth/lib/index.d.ts @@ -576,15 +576,23 @@ export namespace Auth { /** * Android specific settings. */ - android: ActionCodeSettingsAndroid; + android?: ActionCodeSettingsAndroid; + /** * Whether the code should be handled by the app. */ handleCodeInApp?: boolean; + /** * iOS specific settings. */ - iOS: ActionCodeSettingsIos; + iOS?: ActionCodeSettingsIos; + + /** + * Sets the Dynamic Links domain + */ + dynamicLinkDomain?: string; + /** * Sets the URL for the action. */