UNPKG

nativescript-plugin-firebase-updated

Version:
1,080 lines (1,079 loc) 97.7 kB
import * as application from "@nativescript/core/application"; import { Device } from "@nativescript/core/platform"; import { DocumentSnapshot as DocumentSnapshotBase, FieldValue, firebase, GeoPoint, isDocumentReference } from "./firebase-common"; import * as firebaseFunctions from './functions/functions'; import * as firebaseMessaging from "./messaging/messaging"; import { firebaseUtils } from "./utils"; import { getNonce, Sha256 } from "./utils/nonce-util-ios"; firebase._gIDAuthentication = null; firebase._cachedDynamicLink = null; firebase._configured = false; firebase._currentNonce = null; const useExternalPushProvider = NSBundle.mainBundle.infoDictionary.objectForKey("UseExternalPushProvider") === true; let initializeArguments; class DocumentSnapshot extends DocumentSnapshotBase { constructor(snapshot) { super(snapshot.documentID, snapshot.exists, firebaseUtils.toJsObject(snapshot.data()), firebase.firestore._getDocumentReference(snapshot.reference)); this.snapshot = snapshot; this.metadata = { fromCache: this.snapshot.metadata.fromCache, hasPendingWrites: this.snapshot.metadata.pendingWrites }; this.ios = snapshot; } } firebase.authStateListener = null; firebase.addOnMessageReceivedCallback = firebaseMessaging.addOnMessageReceivedCallback; firebase.addOnPushTokenReceivedCallback = firebaseMessaging.addOnPushTokenReceivedCallback; firebase.registerForPushNotifications = firebaseMessaging.registerForPushNotifications; firebase.unregisterForPushNotifications = firebaseMessaging.unregisterForPushNotifications; firebase.getCurrentPushToken = firebaseMessaging.getCurrentPushToken; firebase.registerForInteractivePush = firebaseMessaging.registerForInteractivePush; firebase.subscribeToTopic = firebaseMessaging.subscribeToTopic; firebase.unsubscribeFromTopic = firebaseMessaging.unsubscribeFromTopic; firebase.areNotificationsEnabled = firebaseMessaging.areNotificationsEnabled; firebase.functions = firebaseFunctions; NSNotificationCenter.defaultCenter.addObserverForNameObjectQueueUsingBlock(UIApplicationDidFinishLaunchingNotification, null, NSOperationQueue.mainQueue, appNotification => { if (!firebase._configured) { firebase._configured = true; if (typeof (FIRApp) !== "undefined") { FIRApp.configure(); } } }); firebase.addAppDelegateMethods = appDelegate => { if (typeof (FIRMessaging) !== "undefined" || useExternalPushProvider || typeof (FBSDKApplicationDelegate) !== "undefined") { appDelegate.prototype.applicationDidFinishLaunchingWithOptions = (application, launchOptions) => { if (launchOptions) { const remoteNotification = launchOptions.objectForKey(UIApplicationLaunchOptionsRemoteNotificationKey); if (remoteNotification) { firebaseMessaging.handleRemoteNotification(application, remoteNotification); } } if (typeof (FBSDKApplicationDelegate) !== "undefined") { FBSDKApplicationDelegate.sharedInstance.applicationDidFinishLaunchingWithOptions(application, launchOptions); } return true; }; } if (typeof (FBSDKApplicationDelegate) !== "undefined" || typeof (GIDSignIn) !== "undefined" || typeof (FIRDynamicLink) !== "undefined") { appDelegate.prototype.applicationOpenURLSourceApplicationAnnotation = (application, url, sourceApplication, annotation) => { let result = false; if (typeof (FBSDKApplicationDelegate) !== "undefined") { result = FBSDKApplicationDelegate.sharedInstance.applicationOpenURLSourceApplicationAnnotation(application, url, sourceApplication, annotation); } if (typeof (GIDSignIn) !== "undefined") { result = result || GIDSignIn.sharedInstance().handleURL(url); } if (typeof (FIRDynamicLink) !== "undefined") { const dynamicLink = FIRDynamicLinks.dynamicLinks().dynamicLinkFromCustomSchemeURL(url); if (dynamicLink && dynamicLink.url) { console.log("Dynamic link from " + sourceApplication + ", URL: " + dynamicLink.url.absoluteString); firebase._cachedDynamicLink = { url: dynamicLink.url.absoluteString, minimumAppVersion: dynamicLink.minimumAppVersion }; result = true; } } return result; }; } if (typeof (FBSDKApplicationDelegate) !== "undefined" || typeof (GIDSignIn) !== "undefined" || typeof (FIRDynamicLink) !== "undefined") { appDelegate.prototype.applicationOpenURLOptions = (application, url, options) => { let result = false; if (typeof (FBSDKApplicationDelegate) !== "undefined") { result = FBSDKApplicationDelegate.sharedInstance.applicationOpenURLSourceApplicationAnnotation(application, url, options.valueForKey(UIApplicationOpenURLOptionsSourceApplicationKey), options.valueForKey(UIApplicationOpenURLOptionsAnnotationKey)); } if (typeof (GIDSignIn) !== "undefined") { result = result || GIDSignIn.sharedInstance().handleURL(url); } if (typeof (FIRDynamicLink) !== "undefined") { const absoluteString = url.absoluteString; if (absoluteString.includes(firebase.dynamicLinksCustomScheme)) { result = FIRDynamicLinks.dynamicLinks().handleUniversalLinkCompletion(NSURL.URLWithString(absoluteString.replace(firebase.dynamicLinksCustomScheme, 'https://')), (dynamicLink, error) => { if (dynamicLink !== null && dynamicLink.url !== null) { if (firebase._dynamicLinkCallback) { firebase._dynamicLinkCallback({ url: dynamicLink.url.absoluteString, minimumAppVersion: dynamicLink.minimumAppVersion }); } else { firebase._cachedDynamicLink = { url: dynamicLink.url.absoluteString, minimumAppVersion: dynamicLink.minimumAppVersion }; } } }); return result; } const dynamicLinks = FIRDynamicLinks.dynamicLinks(); const dynamicLink = dynamicLinks.dynamicLinkFromCustomSchemeURL(url); if (dynamicLink && dynamicLink.url !== null) { if (firebase._dynamicLinkCallback) { firebase._dynamicLinkCallback({ url: dynamicLink.url.absoluteString, minimumAppVersion: dynamicLink.minimumAppVersion }); } else { firebase._cachedDynamicLink = { url: dynamicLink.url.absoluteString, minimumAppVersion: dynamicLink.minimumAppVersion }; } result = true; } } return result; }; } if (typeof (FIRDynamicLink) !== "undefined") { appDelegate.prototype.applicationContinueUserActivityRestorationHandler = (application, userActivity, restorationHandler) => { let result = false; if (userActivity.webpageURL) { const fAuth = (typeof (FIRAuth) !== "undefined") ? FIRAuth.auth() : undefined; if (fAuth && fAuth.isSignInWithEmailLink(userActivity.webpageURL.absoluteString)) { const rememberedEmail = firebase.getRememberedEmailForEmailLinkLogin(); if (rememberedEmail !== undefined) { if (fAuth.currentUser) { const onCompletionLink = (result, error) => { if (error) { if (firebase._emailLinkErrorCallback) { firebase._emailLinkErrorCallback(error.localizedDescription); } else { fAuth.signInWithEmailLinkCompletion(rememberedEmail, userActivity.webpageURL.absoluteString, (authData, error) => { if (!error) { firebase.notifyAuthStateListeners({ loggedIn: true, user: toLoginResult(authData.user, authData.additionalUserInfo) }); } }); } } else { firebase.notifyAuthStateListeners({ loggedIn: true, user: toLoginResult(result.user, result.additionalUserInfo) }); } }; const fIRAuthCredential = FIREmailAuthProvider.credentialWithEmailLink(rememberedEmail, userActivity.webpageURL.absoluteString); fAuth.currentUser.linkWithCredentialCompletion(fIRAuthCredential, onCompletionLink); } else { fAuth.signInWithEmailLinkCompletion(rememberedEmail, userActivity.webpageURL.absoluteString, (authData, error) => { if (error) { console.log(error.localizedDescription); } else { firebase.notifyAuthStateListeners({ loggedIn: true, user: toLoginResult(authData.user, authData.additionalUserInfo) }); } }); } } result = true; } else { result = FIRDynamicLinks.dynamicLinks().handleUniversalLinkCompletion(userActivity.webpageURL, (dynamicLink, error) => { if (dynamicLink !== null && dynamicLink.url !== null) { if (firebase._dynamicLinkCallback) { firebase._dynamicLinkCallback({ url: dynamicLink.url.absoluteString, minimumAppVersion: dynamicLink.minimumAppVersion }); } else { firebase._cachedDynamicLink = { url: dynamicLink.url.absoluteString, minimumAppVersion: dynamicLink.minimumAppVersion }; } } }); } } return result; }; } if (typeof (FIRMessaging) !== "undefined" || useExternalPushProvider) { firebaseMessaging.addBackgroundRemoteNotificationHandler(appDelegate); } }; firebase.fetchSignInMethodsForEmail = email => { return new Promise((resolve, reject) => { try { if (typeof (email) !== "string") { reject("A parameter representing an email address is required."); return; } FIRAuth.auth().fetchSignInMethodsForEmailCompletion(email, (methodsNSArray, error) => { if (error) { reject(error.localizedDescription); } else { resolve(firebaseUtils.toJsObject(methodsNSArray)); } }); } catch (ex) { console.log("Error in firebase.fetchSignInMethodsForEmail: " + ex); reject(ex); } }); }; firebase.addOnEmailLinkError = callback => { firebase._emailLinkErrorCallback = callback; }; firebase.addOnDynamicLinkReceivedCallback = callback => { return new Promise((resolve, reject) => { try { if (typeof (FIRDynamicLink) === "undefined") { reject("Set 'dynamic_links' to 'true' in firebase.nativescript.json and remove the platforms/ios folder"); return; } firebase._dynamicLinkCallback = callback; if (firebase._cachedDynamicLink !== null) { callback(firebase._cachedDynamicLink); firebase._cachedDynamicLink = null; } resolve(); } catch (ex) { console.log("Error in firebase.addOnDynamicLinkReceivedCallback: " + ex); reject(ex); } }); }; if (typeof (FIRMessaging) !== "undefined" || useExternalPushProvider) { firebaseMessaging.prepAppDelegate(); } function getAppDelegate() { if (application.ios.delegate === undefined) { let UIApplicationDelegateImpl = class UIApplicationDelegateImpl extends UIResponder { }; UIApplicationDelegateImpl = __decorate([ ObjCClass(UIApplicationDelegate) ], UIApplicationDelegateImpl); application.ios.delegate = UIApplicationDelegateImpl; } return application.ios.delegate; } firebase.addAppDelegateMethods(getAppDelegate()); firebase.getCallbackData = (type, snapshot) => { return { type: type, key: snapshot.key, value: firebaseUtils.toJsObject(snapshot.value) }; }; firebase.init = arg => { return new Promise((resolve, reject) => { if (firebase.initialized) { reject("Firebase already initialized"); return; } firebase.initialized = true; try { try { if (typeof (FIRServerValue) !== "undefined") { firebase.ServerValue = { TIMESTAMP: FIRServerValue.timestamp() }; } } catch (ignore) { } arg = arg || {}; initializeArguments = arg; firebase.dynamicLinksCustomScheme = arg.dynamicLinksCustomScheme; if (FIROptions && FIROptions.defaultOptions() !== null) { FIROptions.defaultOptions().deepLinkURLScheme = NSBundle.mainBundle.bundleIdentifier; } if (typeof (FIRAnalytics) !== "undefined" && FIRAnalytics.setAnalyticsCollectionEnabled) { FIRAnalytics.setAnalyticsCollectionEnabled(arg.analyticsCollectionEnabled !== false); } if (!firebase._configured) { firebase._configured = true; if (typeof (FIRApp) !== "undefined") { FIRApp.configure(); } } if (arg.crashlyticsCollectionEnabled && typeof (Crashlytics) !== "undefined") { Fabric.with(NSArray.arrayWithObject(Crashlytics.class())); } if (typeof (FIRDatabase) !== "undefined") { if (arg.persist) { FIRDatabase.database().persistenceEnabled = true; } } if (typeof (FIRFirestore) !== "undefined") { if (arg.persist === false) { const fIRFirestoreSettings = FIRFirestoreSettings.new(); fIRFirestoreSettings.persistenceEnabled = false; FIRFirestore.firestore().settings = fIRFirestoreSettings; } } if (typeof (FIRAuth) !== "undefined") { if (arg.iOSEmulatorFlush) { try { FIRAuth.auth().signOut(); } catch (signOutErr) { console.log("Sign out of Firebase error: " + signOutErr); } } if (arg.onAuthStateChanged) { firebase.authStateListener = (auth, user) => { arg.onAuthStateChanged({ loggedIn: user !== null, user: toLoginResult(user) }); }; FIRAuth.auth().addAuthStateDidChangeListener(firebase.authStateListener); } if (!firebase.authStateListener) { firebase.authStateListener = (auth, user) => { firebase.notifyAuthStateListeners({ loggedIn: user !== null, user: toLoginResult(user) }); }; FIRAuth.auth().addAuthStateDidChangeListener(firebase.authStateListener); } } if (arg.onDynamicLinkCallback !== undefined) { firebase.addOnDynamicLinkReceivedCallback(arg.onDynamicLinkCallback); } if (typeof (FBSDKAppEvents) !== "undefined") { FBSDKAppEvents.activateApp(); } if (typeof (FIRMessaging) !== "undefined") { firebaseMessaging.initFirebaseMessaging(arg); } if (arg.storageBucket) { if (typeof (FIRStorage) === "undefined") { reject("Uncomment Storage in the plugin's Podfile first"); return; } firebase.storageBucket = FIRStorage.storage().referenceForURL(arg.storageBucket); } resolve(typeof (FIRDatabase) !== "undefined" ? FIRDatabase.database().reference() : undefined); } catch (ex) { console.log("Error in firebase.init: " + ex); reject(ex); } }); }; firebase.getRemoteConfig = arg => { return new Promise((resolve, reject) => { try { if (typeof (FIRRemoteConfig) === "undefined") { reject("Uncomment RemoteConfig in the plugin's Podfile first"); return; } if (arg.properties === undefined) { reject("Argument 'properties' is missing"); return; } const firebaseRemoteConfig = FIRRemoteConfig.remoteConfig(); firebaseRemoteConfig.configSettings = new FIRRemoteConfigSettings({ developerModeEnabled: arg.developerMode || false }); const dic = NSMutableDictionary.new(); for (let p in arg.properties) { const prop = arg.properties[p]; if (prop.default !== undefined) { dic.setObjectForKey(prop.default, prop.key); } } firebaseRemoteConfig.setDefaults(dic); const onCompletion = (remoteConfigFetchStatus, error) => { if (remoteConfigFetchStatus === 1 || remoteConfigFetchStatus === 3) { const activated = firebaseRemoteConfig.activateFetched(); const result = { lastFetch: firebaseRemoteConfig.lastFetchTime, throttled: remoteConfigFetchStatus === 3, properties: {} }; for (let p in arg.properties) { const prop = arg.properties[p]; const key = prop.key; const value = firebaseRemoteConfig.configValueForKey(key).stringValue; result.properties[key] = firebase.strongTypeify(value); } resolve(result); } else { reject(error ? error.localizedDescription : "Unknown error, fetch status: " + remoteConfigFetchStatus); } }; const expirationDuration = arg.cacheExpirationSeconds || 43200; firebaseRemoteConfig.fetchWithExpirationDurationCompletionHandler(expirationDuration, onCompletion); } catch (ex) { console.log("Error in firebase.getRemoteConfig: " + ex); reject(ex); } }); }; firebase.getCurrentUser = arg => { return new Promise((resolve, reject) => { try { const fAuth = FIRAuth.auth(); if (fAuth === null) { reject("Run init() first!"); return; } const user = fAuth.currentUser; if (user) { resolve(toLoginResult(user)); } else { reject(); } } catch (ex) { console.log("Error in firebase.getCurrentUser: " + ex); reject(ex); } }); }; firebase.sendEmailVerification = (actionCodeSettings) => { return new Promise((resolve, reject) => { try { const fAuth = FIRAuth.auth(); if (fAuth === null) { reject("Run init() first!"); return; } const user = fAuth.currentUser; if (user) { const onCompletion = error => { if (error) { reject(error.localizedDescription); } else { resolve(true); } }; if (actionCodeSettings) { const firActionCodeSettings = FIRActionCodeSettings.new(); if (actionCodeSettings.handleCodeInApp !== undefined) { firActionCodeSettings.handleCodeInApp = actionCodeSettings.handleCodeInApp; } if (actionCodeSettings.url) { firActionCodeSettings.URL = NSURL.URLWithString(actionCodeSettings.url); } if (actionCodeSettings.iOS) { if (actionCodeSettings.iOS.bundleId) { firActionCodeSettings.setIOSBundleID(actionCodeSettings.iOS.bundleId); } if (actionCodeSettings.iOS.dynamicLinkDomain) { firActionCodeSettings.dynamicLinkDomain = actionCodeSettings.iOS.dynamicLinkDomain; } } if (actionCodeSettings.android && actionCodeSettings.android.packageName) { firActionCodeSettings.setAndroidPackageNameInstallIfNotAvailableMinimumVersion(actionCodeSettings.android.packageName, actionCodeSettings.android.installApp, actionCodeSettings.android.minimumVersion || null); } user.sendEmailVerificationWithActionCodeSettingsCompletion(firActionCodeSettings, onCompletion); } else { user.sendEmailVerificationWithCompletion(onCompletion); } } else { reject("Log in first"); } } catch (ex) { console.log("Error in firebase.sendEmailVerification: " + ex); reject(ex); } }); }; firebase.logout = arg => { return new Promise((resolve, reject) => { try { FIRAuth.auth().signOut(); firebase.currentAdditionalUserInfo = null; if (typeof (GIDSignIn) !== "undefined") { GIDSignIn.sharedInstance().disconnect(); } if (typeof (FBSDKLoginManager) !== "undefined") { FBSDKLoginManager.alloc().logOut(); } resolve(); } catch (ex) { console.log("Error in firebase.logout: " + ex); reject(ex); } }); }; firebase.unlink = providerId => { return new Promise((resolve, reject) => { try { const user = FIRAuth.auth().currentUser; if (!user) { reject("Not logged in"); return; } user.unlinkFromProviderCompletion(providerId, (user, error) => { if (error) { reject(error.localizedDescription); } else { resolve(user); } }); } catch (ex) { console.log("Error in firebase.logout: " + ex); reject(ex); } }); }; function toLoginResult(user, additionalUserInfo) { if (!user) { return null; } if (additionalUserInfo) { firebase.currentAdditionalUserInfo = additionalUserInfo; } const providers = []; if (user.providerData) { for (let i = 0, l = user.providerData.count; i < l; i++) { const firUserInfo = user.providerData.objectAtIndex(i); const pid = firUserInfo.valueForKey("providerID"); if (pid === "facebook.com" && typeof (FBSDKAccessToken) !== "undefined") { providers.push({ id: pid, token: FBSDKAccessToken.currentAccessToken ? FBSDKAccessToken.currentAccessToken.tokenString : null }); } else if (pid === 'google.com' && typeof (GIDSignIn) !== "undefined" && GIDSignIn.sharedInstance() && GIDSignIn.sharedInstance().currentUser) { var gidUser = GIDSignIn.sharedInstance().currentUser; var gidAuthentication = gidUser.authentication; providers.push({ id: pid, token: gidAuthentication.idToken, code: gidUser.serverAuthCode }); } else if (pid === "apple.com") { } else { providers.push({ id: pid }); } } } const loginResult = { uid: user.uid, anonymous: user.anonymous, isAnonymous: user.anonymous, providers: providers, photoURL: user.photoURL ? user.photoURL.absoluteString : null, email: user.email, emailVerified: user.emailVerified, displayName: user.displayName, phoneNumber: user.phoneNumber, refreshToken: user.refreshToken, metadata: { creationTimestamp: user.metadata.creationDate, lastSignInTimestamp: user.metadata.lastSignInDate }, getIdToken: (forceRefresh) => new Promise((resolve, reject) => { firebase.getAuthToken({ forceRefresh }) .then((result) => resolve(result.token)) .catch(reject); }), getIdTokenResult: (forceRefresh) => new Promise((resolve, reject) => { firebase.getAuthToken({ forceRefresh }) .then((result) => resolve(result)) .catch(reject); }), sendEmailVerification: (actionCodeSettings) => firebase.sendEmailVerification(actionCodeSettings) }; if (firebase.currentAdditionalUserInfo) { loginResult.additionalUserInfo = { providerId: firebase.currentAdditionalUserInfo.providerID, username: firebase.currentAdditionalUserInfo.username, isNewUser: firebase.currentAdditionalUserInfo.newUser, profile: firebaseUtils.toJsObject(firebase.currentAdditionalUserInfo.profile) }; } return loginResult; } firebase.getAuthToken = (arg) => { return new Promise((resolve, reject) => { try { const fAuth = FIRAuth.auth(); if (fAuth === null) { reject("Run init() first!"); return; } const user = fAuth.currentUser; if (user) { user.getIDTokenResultForcingRefreshCompletion(arg.forceRefresh, (result, error) => { if (error) { reject(error.localizedDescription); } else { resolve({ token: result.token, claims: firebaseUtils.toJsObject(result.claims), signInProvider: result.signInProvider, expirationTime: firebaseUtils.toJsObject(result.expirationDate), issuedAtTime: firebaseUtils.toJsObject(result.issuedAtDate), authTime: firebaseUtils.toJsObject(result.authDate) }); } }); } else { reject("Log in first"); } } catch (ex) { console.log("Error in firebase.getAuthToken: " + ex); reject(ex); } }); }; firebase.login = arg => { return new Promise((resolve, reject) => { try { const onCompletionWithAuthResult = (authResult, error) => { if (error) { if (typeof (GIDSignIn) !== "undefined") { GIDSignIn.sharedInstance().disconnect(); } reject(error.localizedDescription); } else { resolve(toLoginResult(authResult && authResult.user, authResult && authResult.additionalUserInfo)); firebase.notifyAuthStateListeners({ loggedIn: true, user: toLoginResult(authResult.user) }); } }; const fAuth = FIRAuth.auth(); if (fAuth === null) { reject("Run init() first!"); return; } firebase.moveLoginOptionsToObjects(arg); if (arg.type === firebase.LoginType.ANONYMOUS) { fAuth.signInAnonymouslyWithCompletion(onCompletionWithAuthResult); } else if (arg.type === firebase.LoginType.PASSWORD) { if (!arg.passwordOptions || !arg.passwordOptions.email || !arg.passwordOptions.password) { reject("Auth type PASSWORD requires an 'passwordOptions.email' and 'passwordOptions.password' argument"); return; } const fIRAuthCredential = FIREmailAuthProvider.credentialWithEmailPassword(arg.passwordOptions.email, arg.passwordOptions.password); if (fAuth.currentUser) { const onCompletionLink = (authData, error) => { if (error) { reject(error.localizedDescription); return; } else { onCompletionWithAuthResult(authData, error); } }; fAuth.currentUser.linkWithCredentialCompletion(fIRAuthCredential, onCompletionLink); } else { fAuth.signInWithEmailPasswordCompletion(arg.passwordOptions.email, arg.passwordOptions.password, onCompletionWithAuthResult); } } else if (arg.type === firebase.LoginType.EMAIL_LINK) { if (!arg.emailLinkOptions || !arg.emailLinkOptions.email) { reject("Auth type EMAIL_LINK requires an 'emailLinkOptions.email' argument"); return; } if (!arg.emailLinkOptions.url) { reject("Auth type EMAIL_LINK requires an 'emailLinkOptions.url' argument"); return; } const firActionCodeSettings = FIRActionCodeSettings.new(); firActionCodeSettings.URL = NSURL.URLWithString(arg.emailLinkOptions.url); firActionCodeSettings.handleCodeInApp = true; firActionCodeSettings.setIOSBundleID(arg.emailLinkOptions.iOS ? arg.emailLinkOptions.iOS.bundleId : NSBundle.mainBundle.bundleIdentifier); firActionCodeSettings.setAndroidPackageNameInstallIfNotAvailableMinimumVersion(arg.emailLinkOptions.android ? arg.emailLinkOptions.android.packageName : NSBundle.mainBundle.bundleIdentifier, arg.emailLinkOptions.android ? arg.emailLinkOptions.android.installApp || false : false, arg.emailLinkOptions.android ? arg.emailLinkOptions.android.minimumVersion || "1" : "1"); fAuth.sendSignInLinkToEmailActionCodeSettingsCompletion(arg.emailLinkOptions.email, firActionCodeSettings, (error) => { if (error) { reject(error.localizedDescription); return; } firebase.rememberEmailForEmailLinkLogin(arg.emailLinkOptions.email); resolve(); }); } else if (arg.type === firebase.LoginType.PHONE) { if (!arg.phoneOptions || !arg.phoneOptions.phoneNumber) { reject("Auth type PHONE requires a 'phoneOptions.phoneNumber' argument"); return; } FIRPhoneAuthProvider.provider().verifyPhoneNumberUIDelegateCompletion(arg.phoneOptions.phoneNumber, null, (verificationID, error) => { if (error) { reject(error.localizedDescription); return; } firebase.requestPhoneAuthVerificationCode(userResponse => { if (userResponse === undefined || userResponse === '') { reject("Prompt was canceled"); return; } const fIRAuthCredential = FIRPhoneAuthProvider.provider().credentialWithVerificationIDVerificationCode(verificationID, userResponse); if (fAuth.currentUser) { const onCompletionLink = (authData, error) => { if (error) { reject(error.localizedDescription); return; } else { onCompletionWithAuthResult(authData, error); } }; fAuth.currentUser.linkWithCredentialCompletion(fIRAuthCredential, onCompletionLink); } else { fAuth.signInWithCredentialCompletion(fIRAuthCredential, onCompletionWithAuthResult); } }, arg.phoneOptions.verificationPrompt); }); } else if (arg.type === firebase.LoginType.CUSTOM) { if (!arg.customOptions || (!arg.customOptions.token && !arg.customOptions.tokenProviderFn)) { reject("Auth type CUSTOM requires a 'customOptions.token' or 'customOptions.tokenProviderFn' argument"); return; } if (arg.customOptions.token) { fAuth.signInWithCustomTokenCompletion(arg.customOptions.token, onCompletionWithAuthResult); } else if (arg.customOptions.tokenProviderFn) { arg.customOptions.tokenProviderFn() .then(token => { fAuth.signInWithCustomTokenCompletion(token, onCompletionWithAuthResult); }, error => { reject(error); }); } } else if (arg.type === firebase.LoginType.FACEBOOK) { if (typeof (FBSDKLoginManager) === "undefined") { reject("Facebook SDK not installed - see Podfile"); return; } const onFacebookCompletion = (fbSDKLoginManagerLoginResult, error) => { if (error) { console.log("Facebook login error " + error); reject(error.localizedDescription); } else if (fbSDKLoginManagerLoginResult.isCancelled) { reject("login cancelled"); } else { const fIRAuthCredential = FIRFacebookAuthProvider.credentialWithAccessToken(FBSDKAccessToken.currentAccessToken.tokenString); if (fAuth.currentUser) { const onCompletionLink = (authData, error) => { if (error) { reject(error.localizedDescription); return; } else { onCompletionWithAuthResult(authData); } }; fAuth.currentUser.linkWithCredentialCompletion(fIRAuthCredential, onCompletionLink); } else { fAuth.signInWithCredentialCompletion(fIRAuthCredential, onCompletionWithAuthResult); } } }; const fbSDKLoginManager = FBSDKLoginManager.new(); let scopes = ["public_profile", "email"]; if (arg.facebookOptions && arg.facebookOptions.scopes) { scopes = arg.facebookOptions.scopes; } fbSDKLoginManager.logInWithPermissionsFromViewControllerHandler(scopes, null, onFacebookCompletion); } else if (arg.type === firebase.LoginType.APPLE) { if (parseInt(Device.osVersion) < 13) { reject("Sign in with Apple requires iOS 13 or higher. You're running iOS " + Device.osVersion); return; } firebase._currentNonce = getNonce(32); const sha256Nonce = Sha256(firebase._currentNonce); const appleIDProvider = ASAuthorizationAppleIDProvider.new(); const appleIDRequest = appleIDProvider.createRequest(); let scopes = [ASAuthorizationScopeFullName, ASAuthorizationScopeEmail]; if (arg.appleOptions && arg.appleOptions.scopes) { scopes = []; arg.appleOptions.scopes.forEach(scope => { if (scope === "name") { scopes.push(ASAuthorizationScopeFullName); } else if (scope === "email") { scopes.push(ASAuthorizationScopeEmail); } else { console.log("Unknown scope: " + scope); } }); } appleIDRequest.requestedScopes = scopes; appleIDRequest.nonce = sha256Nonce; const authorizationController = ASAuthorizationController.alloc().initWithAuthorizationRequests([appleIDRequest]); const delegate = ASAuthorizationControllerDelegateImpl.createWithOwnerAndResolveReject(new WeakRef(this), resolve, reject); CFRetain(delegate); authorizationController.delegate = delegate; authorizationController.presentationContextProvider = ASAuthorizationControllerPresentationContextProvidingImpl.createWithOwnerAndCallback(new WeakRef(this)); authorizationController.performRequests(); } else if (arg.type === firebase.LoginType.GOOGLE) { if (typeof (GIDSignIn) === "undefined") { reject("Google Sign In not installed - see Podfile"); return; } const sIn = GIDSignIn.sharedInstance(); sIn.presentingViewController = arg.ios && arg.ios.controller ? arg.ios.controller : application.ios.rootController; sIn.clientID = FIRApp.defaultApp().options.clientID; if (arg.googleOptions && arg.googleOptions.serverClientID) { sIn.serverClientID = arg.googleOptions.serverClientID; } if (arg.googleOptions && arg.googleOptions.hostedDomain) { sIn.hostedDomain = arg.googleOptions.hostedDomain; } if (arg.googleOptions && arg.googleOptions.scopes) { sIn.scopes = arg.googleOptions.scopes; } let delegate = GIDSignInDelegateImpl.new().initWithCallback((user, error) => { if (error === null) { firebase._gIDAuthentication = user.authentication; const fIRAuthCredential = FIRGoogleAuthProvider.credentialWithIDTokenAccessToken(firebase._gIDAuthentication.idToken, firebase._gIDAuthentication.accessToken); let googleAlreadyLinked = false; if (fAuth.currentUser) { for (var i = 0, l = fAuth.currentUser.providerData.count; i < l; i++) { const firUserInfo = fAuth.currentUser.providerData.objectAtIndex(i); const pid = firUserInfo.valueForKey('providerID'); if (pid === 'google.com') { googleAlreadyLinked = true; break; } } } if (fAuth.currentUser && !googleAlreadyLinked) { const onCompletionLink = (user, error) => { if (error) { reject(error.localizedDescription); return; } else { onCompletionWithAuthResult(user); } }; fAuth.currentUser.linkWithCredentialCompletion(fIRAuthCredential, onCompletionLink); } else { fAuth.signInWithCredentialCompletion(fIRAuthCredential, onCompletionWithAuthResult); } } else { reject(error.localizedDescription); } CFRelease(delegate); delegate = undefined; }); CFRetain(delegate); sIn.delegate = delegate; sIn.signIn(); } else { reject("Unsupported auth type: " + arg.type); } } catch (ex) { console.log("Error in firebase.login: " + ex); reject(ex); } }); }; firebase.reauthenticate = arg => { return new Promise((resolve, reject) => { try { const fAuth = FIRAuth.auth(); if (fAuth === null) { reject("Run init() first!"); return; } const user = fAuth.currentUser; if (user === null) { reject("no current user"); return; } firebase.moveLoginOptionsToObjects(arg); let authCredential = null; if (arg.type === firebase.LoginType.PASSWORD) { if (!arg.passwordOptions || !arg.passwordOptions.email || !arg.passwordOptions.password) { reject("Auth type PASSWORD requires an 'passwordOptions.email' and 'passwordOptions.password' argument"); return; } authCredential = FIREmailAuthProvider.credentialWithEmailPassword(arg.passwordOptions.email, arg.passwordOptions.password); } else if (arg.type === firebase.LoginType.GOOGLE) { if (!firebase._gIDAuthentication) { reject("Not currently logged in with Google"); return; } authCredential = FIRGoogleAuthProvider.credentialWithIDTokenAccessToken(firebase._gIDAuthentication.idToken, firebase._gIDAuthentication.accessToken); } else if (arg.type === firebase.LoginType.FACEBOOK) { if (!FBSDKAccessToken.currentAccessToken) { reject("Not currently logged in with Facebook"); return; } authCredential = FIRFacebookAuthProvider.credentialWithAccessToken(FBSDKAccessToken.currentAccessToken.tokenString); } if (authCredential === null) { reject("arg.type should be one of LoginType.PASSWORD | LoginType.GOOGLE | LoginType.FACEBOOK"); return; } const onCompletion = (authResult, error) => { if (error) { reject(error.localizedDescription); } else { firebase.notifyAuthStateListeners({ loggedIn: true, user: toLoginResult(authResult.user) }); resolve(toLoginResult(authResult && authResult.user, authResult && authResult.additionalUserInfo)); } }; user.reauthenticateWithCredentialCompletion(authCredential, onCompletion); } catch (ex) { console.log("Error in firebase.reauthenticate: " + ex); reject(ex); } }); }; firebase.reloadUser = () => { return new Promise((resolve, reject) => { try { const user = FIRAuth.auth().currentUser; if (user === null) { reject("no current user"); return; } const onCompletion = error => { if (error) { reject(error.localizedDescription); } else { resolve(); } }; user.reloadWithCompletion(onCompletion); } catch (ex) { console.log("Error in firebase.reloadUser: " + ex); reject(ex); } }); }; firebase.sendPasswordResetEmail = (email) => { return new Promise((resolve, reject) => { try { const onCompletion = error => { if (error) { reject(error.localizedDescription); } else { resolve(); } }; FIRAuth.auth().sendPasswordResetWithEmailCompletion(email, onCompletion); } catch (ex) { console.log("Error in firebase.sendPasswordResetEmail: " + ex); reject(ex); } }); }; firebase.updateEmail = (newEmail) => { return new Promise((resolve, reject) => { try { const onCompletion = error => { if (error) { reject(error.localizedDescription); } else { resolve(); } }; const user = FIRAuth.auth().currentUser; if (user === null) { reject("no current user"); } else { user.updateEmailCompletion(newEmail, onCompletion); } } catch (ex) { console.log("Error in firebase.updateEmail: " + ex); reject(ex); } }); }; firebase.updatePassword = (newPassword) => { return new Promise((resolve, reject) => { try { const onCompletion = error => { if (error) { reject(error.localizedDescription); } else { resolve(); } }; const user = FIRAuth.auth().currentUser; if (user === null) { reject("no current user"); } else { user.updatePasswordCompletion(newPassword, onCompletion); } } catch (ex) { console.log("Error in firebase.updatePassword: " + ex); reject(ex); } }); }; firebase.createUser = arg => { return new Promise((resolve, reject) => { try { const onCompletion = (authResult, error) => { if (error) { reject(error.localizedDescription); } else { resolve(toLoginResult(authResult.user, authResult.additionalUserInfo)); } }; if (!arg.email || !arg.password) { reject("Creating a user requires an email and password argument"); } else { FIRAuth.auth().createUserWithEmailPasswordCompletion(arg.email, arg.password, onCompletion); } } catch (ex) { console.log("Error in firebase.createUser: " + ex);