diff --git a/.github/workflows/create_test_patches.yml b/.github/workflows/create_test_patches.yml
index e9fbb307f4..cdc4b665fd 100644
--- a/.github/workflows/create_test_patches.yml
+++ b/.github/workflows/create_test_patches.yml
@@ -78,14 +78,16 @@ jobs:
mkdir patches || true
for PACKAGE in $PACKAGE_LIST; do
echo "Installing package $PACKAGE into fresh template app, then clobbering with PR version"
- yarn add @react-native-firebase/$PACKAGE
- pushd node_modules/@react-native-firebase
- tar -zxf $HOME/packages/react-native-firebase-${PACKAGE}-v*
- mv $PACKAGE/package.json package/
- \rm -fr $PACKAGE
- mv package $PACKAGE
- popd
- npx patch-package @react-native-firebase/$PACKAGE || true
+ yarn add @react-native-firebase/$PACKAGE || true
+ if [ -d node_modules/@react-native-firebase/$PACKAGE ]; then
+ pushd node_modules/@react-native-firebase
+ tar -zxf $HOME/packages/react-native-firebase-${PACKAGE}-v*
+ mv $PACKAGE/package.json package/
+ \rm -fr $PACKAGE
+ mv package $PACKAGE
+ popd
+ npx patch-package @react-native-firebase/$PACKAGE || true
+ fi
done
ls -la $HOME/template/patches
shell: bash
@@ -95,9 +97,9 @@ jobs:
with:
name: patches
path: ~/template/patches/
-
+
# create a comment on the PR and any related issues with a direct link to the archive,
- # a call for testers, and perhaps a paste-able set of commands to install them
+ # a call for testers, and perhaps a paste-able set of commands to install them
# (mkdir patches, curl -o etc, npx patch-package)
# You need an artifact id to get a download link for it.
# You need a workflow run id to get an artifact id.
diff --git a/.github/workflows/tests_e2e_ios.yml b/.github/workflows/tests_e2e_ios.yml
index 5cdfa917a5..471f6c60d1 100644
--- a/.github/workflows/tests_e2e_ios.yml
+++ b/.github/workflows/tests_e2e_ios.yml
@@ -102,8 +102,8 @@ jobs:
- name: Pod Install
uses: nick-invision/retry@v2
with:
- timeout_minutes: 2
- retry_wait_seconds: 60
+ timeout_minutes: 10
+ retry_wait_seconds: 30
max_attempts: 3
command: yarn tests:ios:pod:install
@@ -168,9 +168,7 @@ jobs:
- name: Detox Test
timeout-minutes: 10
- run: |
- cd tests
- ./node_modules/.bin/nyc ./node_modules/.bin/detox test --debug-synchronization 200 --configuration ios.sim.debug
+ run: yarn tests:ios:test-cover
- name: Compress Simulator Log
if: always()
diff --git a/.spellcheck.dict.txt b/.spellcheck.dict.txt
index a4957b40e5..74087c8078 100644
--- a/.spellcheck.dict.txt
+++ b/.spellcheck.dict.txt
@@ -6,6 +6,8 @@ Analytics
analytics
APIs
APIs.
+AppAttest
+AppCheck
APNs
AirPods
async
@@ -42,7 +44,9 @@ Deprecations
Detox
DEVEX
Diarmid
+DeviceCheck
dropdown
+e2e
EEA
Ehesp
enum
@@ -55,6 +59,7 @@ firebase-ios-sdk
Firestore
getIdToken
GDPR
+GDPR-compliant
globals
Gradle
gradle
@@ -90,6 +95,7 @@ namespaced
natively
NDK
Node.js
+non-firebase
NoSQL
Notifee
NPE
@@ -121,6 +127,7 @@ RN60
RN61
RNFB
RNFirebase
+SafetyNet
Salakar
scalable
scrollable
@@ -150,6 +157,7 @@ uid
uncomment
unhandled
unsubscriber
+untampered
utils
Utils
v5
diff --git a/README.md b/README.md
index db66eb13bc..b74269aa3e 100644
--- a/README.md
+++ b/README.md
@@ -44,6 +44,7 @@ The main package that you interface with is `App` (`@react-native-firebase/app`)
| -------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| [Analytics](/packages/analytics) | [](https://www.npmjs.com/package/@react-native-firebase/analytics) |
| [App](/packages/app) | [](https://www.npmjs.com/package/@react-native-firebase/app) |
+| [AppCheck](/packages/app-check) | [](https://www.npmjs.com/package/@react-native-firebase/app-check) |
| [Authentication](/packages/auth) | [](https://www.npmjs.com/package/@react-native-firebase/auth) |
| [Cloud Firestore](/packages/firestore) | [](https://www.npmjs.com/package/@react-native-firebase/firestore) |
| [Cloud Functions](/packages/functions) | [](https://www.npmjs.com/package/@react-native-firebase/functions) |
diff --git a/docs/analytics/screen-tracking.md b/docs/analytics/screen-tracking.md
index 953779b97d..c177d288cd 100644
--- a/docs/analytics/screen-tracking.md
+++ b/docs/analytics/screen-tracking.md
@@ -2,7 +2,7 @@
title: Screen Tracking
description: Setup Firebase Analytics to track your in-app screen flow.
previous: /analytics/usage
-next: /
+next: /app-check/usage
---
Standard React Native applications run inside a single `Activity`/`ViewController`, meaning any screen changes won't be
diff --git a/docs/app-check/usage/index.md b/docs/app-check/usage/index.md
new file mode 100644
index 0000000000..9730c9e146
--- /dev/null
+++ b/docs/app-check/usage/index.md
@@ -0,0 +1,94 @@
+---
+title: App Check
+description: Installation and getting started with App Check.
+icon: //static.invertase.io/assets/social/firebase-logo.png
+next: /auth/usage
+previous: /analytics/screen-tracking
+---
+
+# Installation
+
+This module requires that the `@react-native-firebase/app` module is already setup and installed. To install the "app"
+module, view the [Getting Started](/) documentation.
+
+```bash
+# Install & setup the app module
+yarn add @react-native-firebase/app
+
+# Install the app-check module
+yarn add @react-native-firebase/app-check
+
+# If you're developing your app using iOS, run this command
+cd ios/ && pod install
+```
+
+App Check requires you set the minimum iOS Deployment version in `ios/Podfile` to `11.0` or greater.
+
+You may have Xcode compiler errors after including the App Check module, specifically referencing linker problems and missing directories.
+
+You may find excluding the `i386` architecture via an addition to the `ios/Podfile` `post_install` hook like the below works:
+
+```ruby
+ installer.aggregate_targets.each do |aggregate_target|
+ aggregate_target.user_project.native_targets.each do |target|
+ target.build_configurations.each do |config|
+ config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO'
+ config.build_settings['EXCLUDED_ARCHS'] = 'i386'
+ end
+ end
+ aggregate_target.user_project.save
+ end
+```
+
+# What does it do
+
+App Check works alongside other Firebase services to help protect your backend resources from abuse, such as billing fraud or phishing. With App Check, devices running your app will use an app or device attestation provider that attests to one or both of the following:
+
+- Requests originate from your authentic app
+- Requests originate from an authentic, untampered device
+
+This attestation is attached to every request your app makes to your Firebase backend resources.
+
+
+
+
+
+ React Native Firebase - AppCheck
+
+
+
+ Built and maintained with 💛 by Invertase. +
+ + +--- diff --git a/packages/app-check/RNFBAppcheck.podspec b/packages/app-check/RNFBAppcheck.podspec new file mode 100644 index 0000000000..a401d72ef5 --- /dev/null +++ b/packages/app-check/RNFBAppcheck.podspec @@ -0,0 +1,45 @@ +require 'json' +package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) +appPackage = JSON.parse(File.read(File.join('..', 'app', 'package.json'))) + +coreVersionDetected = appPackage['version'] +coreVersionRequired = package['peerDependencies'][appPackage['name']] +firebase_sdk_version = appPackage['sdkVersions']['ios']['firebase'] +if coreVersionDetected != coreVersionRequired + Pod::UI.warn "NPM package '#{package['name']}' depends on '#{appPackage['name']}' v#{coreVersionRequired} but found v#{coreVersionDetected}, this might cause build issues or runtime crashes." +end + +Pod::Spec.new do |s| + s.name = "RNFBAppCheck" + s.version = package["version"] + s.description = package["description"] + s.summary = <<-DESC + A well tested feature rich Firebase implementation for React Native, supporting iOS & Android. + DESC + s.homepage = "http://invertase.io/oss/react-native-firebase" + s.license = package['license'] + s.authors = "Invertase Limited" + s.source = { :git => "https://github.com/invertase/react-native-firebase.git", :tag => "v#{s.version}" } + s.social_media_url = 'http://twitter.com/invertaseio' + s.ios.deployment_target = "11.0" + s.source_files = 'ios/**/*.{h,m}' + + # React Native dependencies + s.dependency 'React-Core' + s.dependency 'RNFBApp' + + if defined?($FirebaseSDKVersion) + Pod::UI.puts "#{s.name}: Using user specified Firebase SDK version '#{$FirebaseSDKVersion}'" + firebase_sdk_version = $FirebaseSDKVersion + end + + # Firebase dependencies + s.dependency 'Firebase/AppCheck', firebase_sdk_version + + if defined?($RNFirebaseAsStaticFramework) + Pod::UI.puts "#{s.name}: Using overridden static_framework value of '#{$RNFirebaseAsStaticFramework}'" + s.static_framework = $RNFirebaseAsStaticFramework + else + s.static_framework = false + end +end diff --git a/packages/app-check/__tests__/appcheck.test.ts b/packages/app-check/__tests__/appcheck.test.ts new file mode 100644 index 0000000000..3e7c9854a7 --- /dev/null +++ b/packages/app-check/__tests__/appcheck.test.ts @@ -0,0 +1,21 @@ +import { firebase } from '../lib'; + +describe('appCheck()', function () { + describe('namespace', function () { + it('accessible from firebase.app()', function () { + const app = firebase.app(); + expect(app.appCheck).toBeDefined(); + expect(app.appCheck().app).toEqual(app); + }); + + it('supports multiple apps', async function () { + expect(firebase.appCheck().app.name).toEqual('[DEFAULT]'); + expect(firebase.appCheck(firebase.app('secondaryFromNative')).app.name).toEqual( + 'secondaryFromNative', + ); + expect(firebase.app('secondaryFromNative').appCheck().app.name).toEqual( + 'secondaryFromNative', + ); + }); + }); +}); diff --git a/packages/app-check/android/.editorconfig b/packages/app-check/android/.editorconfig new file mode 100644 index 0000000000..670398e990 --- /dev/null +++ b/packages/app-check/android/.editorconfig @@ -0,0 +1,10 @@ +# editorconfig +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/packages/app-check/android/build.gradle b/packages/app-check/android/build.gradle new file mode 100644 index 0000000000..e09aa288b6 --- /dev/null +++ b/packages/app-check/android/build.gradle @@ -0,0 +1,101 @@ +import io.invertase.gradle.common.PackageJson + +buildscript { + // The Android Gradle plugin is only required when opening the android folder stand-alone. + // This avoids unnecessary downloads and potential conflicts when the library is included as a + // module dependency in an application project. + if (project == rootProject) { + repositories { + google() + mavenCentral() + } + + dependencies { + classpath('com.android.tools.build:gradle:7.0.0') + } + } +} + +plugins { + id 'io.invertase.gradle.build' version '1.5' +} + +def appProject +if (findProject(':@react-native-firebase_app')) { + appProject = project(':@react-native-firebase_app') +} else if (findProject(':react-native-firebase_app')) { + appProject = project(':react-native-firebase_app') +} else { + throw new GradleException('Could not find the react-native-firebase/app package, have you installed it?') +} +def packageJson = PackageJson.getForProject(project) +def appPackageJson = PackageJson.getForProject(appProject) +def firebaseBomVersion = appPackageJson['sdkVersions']['android']['firebase'] +def jsonMinSdk = appPackageJson['sdkVersions']['android']['minSdk'] +def jsonTargetSdk = appPackageJson['sdkVersions']['android']['targetSdk'] +def jsonCompileSdk = appPackageJson['sdkVersions']['android']['compileSdk'] +def jsonBuildTools = appPackageJson['sdkVersions']['android']['buildTools'] +def coreVersionDetected = appPackageJson['version'] +def coreVersionRequired = packageJson['peerDependencies'][appPackageJson['name']] +// Only log after build completed so log warning appears at the end +if (coreVersionDetected != coreVersionRequired) { + gradle.buildFinished { + project.logger.warn("ReactNativeFirebase WARNING: NPM package '${packageJson['name']}' depends on '${appPackageJson['name']}' v${coreVersionRequired} but found v${coreVersionDetected}, this might cause build issues or runtime crashes.") + } +} + +project.ext { + set('react-native', [ + versions: [ + android : [ + minSdk : jsonMinSdk, + targetSdk : jsonTargetSdk, + compileSdk: jsonCompileSdk, + // optional as gradle.buildTools comes with one by default + // overriding here though to match the version RN uses + buildTools: jsonBuildTools + ], + + firebase: [ + bom: firebaseBomVersion, + ], + ], + ]) +} + +android { + defaultConfig { + multiDexEnabled true + } + lintOptions { + disable 'GradleCompatible' + abortOnError false + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + sourceSets { + main { + java.srcDirs = ['src/main/java', 'src/reactnative/java'] + } + } +} + +repositories { + google() + mavenCentral() +} + +dependencies { + api appProject + implementation platform("com.google.firebase:firebase-bom:${ReactNative.ext.getVersion('firebase', 'bom')}") + // These are beta, so they are not in the BoM yet. We have to specify the versions explicitly. + implementation 'com.google.firebase:firebase-appcheck-safetynet:16.0.0-beta02' + debugImplementation 'com.google.firebase:firebase-appcheck-debug:16.0.0-beta02' +} + +ReactNative.shared.applyPackageVersion() +ReactNative.shared.applyDefaultExcludes() +ReactNative.module.applyAndroidVersions() +ReactNative.module.applyReactNativeDependency('api') diff --git a/packages/app-check/android/lint.xml b/packages/app-check/android/lint.xml new file mode 100644 index 0000000000..c3dd72aca0 --- /dev/null +++ b/packages/app-check/android/lint.xml @@ -0,0 +1,5 @@ + +Built and maintained with 💛 by Invertase.
-- 💼 Hire Us | - ☕️ Sponsor Us | - 💻 Work With Us -
---- diff --git a/scripts/_TEMPLATE_/RNFB_Template_.podspec b/scripts/_TEMPLATE_/RNFB_Template_.podspec index c0069d6da6..2e7929e902 100644 --- a/scripts/_TEMPLATE_/RNFB_Template_.podspec +++ b/scripts/_TEMPLATE_/RNFB_Template_.podspec @@ -1,5 +1,13 @@ require 'json' package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) +appPackage = JSON.parse(File.read(File.join('..', 'app', 'package.json'))) + +coreVersionDetected = appPackage['version'] +coreVersionRequired = package['peerDependencies'][appPackage['name']] +firebase_sdk_version = appPackage['sdkVersions']['ios']['firebase'] +if coreVersionDetected != coreVersionRequired + Pod::UI.warn "NPM package '#{package['name']}' depends on '#{appPackage['name']}' v#{coreVersionRequired} but found v#{coreVersionDetected}, this might cause build issues or runtime crashes." +end Pod::Spec.new do |s| s.name = "RNFB_Template_" @@ -13,10 +21,25 @@ Pod::Spec.new do |s| s.authors = "Invertase Limited" s.source = { :git => "https://github.com/invertase/react-native-firebase.git", :tag => "v#{s.version}" } s.social_media_url = 'http://twitter.com/invertaseio' - s.ios.deployment_target = "9.0" + s.ios.deployment_target = "10.0" s.source_files = 'ios/**/*.{h,m}' + + # React Native dependencies s.dependency 'React-Core' - s.dependency 'Firebase/Core', '~> 5.20.2' s.dependency 'RNFBApp' - s.static_framework = true + + if defined?($FirebaseSDKVersion) + Pod::UI.puts "#{s.name}: Using user specified Firebase SDK version '#{$FirebaseSDKVersion}'" + firebase_sdk_version = $FirebaseSDKVersion + end + + # Firebase dependencies + s.dependency 'Firebase/_Template_', firebase_sdk_version + + if defined?($RNFirebaseAsStaticFramework) + Pod::UI.puts "#{s.name}: Using overridden static_framework value of '#{$RNFirebaseAsStaticFramework}'" + s.static_framework = $RNFirebaseAsStaticFramework + else + s.static_framework = false + end end diff --git a/scripts/_TEMPLATE_/__tests__/_template_.test.ts b/scripts/_TEMPLATE_/__tests__/_template_.test.ts new file mode 100644 index 0000000000..a2db50ab6f --- /dev/null +++ b/scripts/_TEMPLATE_/__tests__/_template_.test.ts @@ -0,0 +1,22 @@ +import { firebase } from '../lib'; + +describe('_template_()', function () { + describe('namespace', function () { + it('accessible from firebase.app()', function () { + const app = firebase.app(); + expect(app._template_).toBeDefined(); + expect(app._template_().app).toEqual(app); + }); + + // disabled as pending if module.options.hasMultiAppSupport = true + xit('supports multiple apps', async function () { + expect(firebase._template_().app.name).toEqual('[DEFAULT]'); + expect(firebase._template_(firebase.app('secondaryFromNative')).app.name).toEqual( + 'secondaryFromNative', + ); + expect(firebase.app('secondaryFromNative')._template_().app.name).toEqual( + 'secondaryFromNative', + ); + }); + }); +}); diff --git a/scripts/_TEMPLATE_/android/build.gradle b/scripts/_TEMPLATE_/android/build.gradle index 6e01719770..296c7a46e5 100644 --- a/scripts/_TEMPLATE_/android/build.gradle +++ b/scripts/_TEMPLATE_/android/build.gradle @@ -1,10 +1,18 @@ +import io.invertase.gradle.common.PackageJson + buildscript { - repositories { - google() - mavenCentral() - } - dependencies { + // The Android Gradle plugin is only required when opening the android folder stand-alone. + // This avoids unnecessary downloads and potential conflicts when the library is included as a + // module dependency in an application project. + if (project == rootProject) { + repositories { + google() + mavenCentral() + } + + dependencies { classpath("com.android.tools.build:gradle:7.0.0") + } } } @@ -12,20 +20,44 @@ plugins { id "io.invertase.gradle.build" version "1.5" } +def appProject +if (findProject(':@react-native-firebase_app')) { + appProject = project(':@react-native-firebase_app') +} else if (findProject(':react-native-firebase_app')) { + appProject = project(':react-native-firebase_app') +} else { + throw new GradleException('Could not find the react-native-firebase/app package, have you installed it?') +} +def packageJson = PackageJson.getForProject(project) +def appPackageJson = PackageJson.getForProject(appProject) +def firebaseBomVersion = appPackageJson['sdkVersions']['android']['firebase'] +def jsonMinSdk = appPackageJson['sdkVersions']['android']['minSdk'] +def jsonTargetSdk = appPackageJson['sdkVersions']['android']['targetSdk'] +def jsonCompileSdk = appPackageJson['sdkVersions']['android']['compileSdk'] +def jsonBuildTools = appPackageJson['sdkVersions']['android']['buildTools'] +def coreVersionDetected = appPackageJson['version'] +def coreVersionRequired = packageJson['peerDependencies'][appPackageJson['name']] +// Only log after build completed so log warning appears at the end +if (coreVersionDetected != coreVersionRequired) { + gradle.buildFinished { + project.logger.warn("ReactNativeFirebase WARNING: NPM package '${packageJson['name']}' depends on '${appPackageJson['name']}' v${coreVersionRequired} but found v${coreVersionDetected}, this might cause build issues or runtime crashes.") + } +} + project.ext { set('react-native', [ versions: [ - android : [ - minSdk : 16, - targetSdk : 30, - compileSdk: 30, + android : [ + minSdk : jsonMinSdk, + targetSdk : jsonTargetSdk, + compileSdk: jsonCompileSdk, // optional as gradle.buildTools comes with one by default // overriding here though to match the version RN uses - buildTools: "31.0.0" + buildTools: jsonBuildTools ], - firebase : [ - bom: "28.3.0" + firebase: [ + bom: firebaseBomVersion, ], ], ]) @@ -43,6 +75,11 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + sourceSets { + main { + java.srcDirs = ['src/main/java', 'src/reactnative/java'] + } + } } repositories { @@ -51,7 +88,7 @@ repositories { } dependencies { - api project(':@react-native-firebase_app') + api appProject implementation platform("com.google.firebase:firebase-bom:${ReactNative.ext.getVersion("firebase", "bom")}") implementation "com.google.firebase:firebase-_template_" } diff --git a/scripts/_TEMPLATE_/android/src/main/java/io/invertase/firebase/_template_/ReactNativeFirebase_Template_Module.java b/scripts/_TEMPLATE_/android/src/main/java/io/invertase/firebase/_template_/ReactNativeFirebase_Template_Module.java index 5e9dbc0c61..f2ec792df6 100644 --- a/scripts/_TEMPLATE_/android/src/main/java/io/invertase/firebase/_template_/ReactNativeFirebase_Template_Module.java +++ b/scripts/_TEMPLATE_/android/src/main/java/io/invertase/firebase/_template_/ReactNativeFirebase_Template_Module.java @@ -17,17 +17,7 @@ * */ -import android.app.Activity; - -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.ReadableMapKeySetIterator; - -import javax.annotation.Nullable; - +import com.facebook.react.bridge.*; import io.invertase.firebase.common.ReactNativeFirebaseModule; public class ReactNativeFirebase_Template_Module extends ReactNativeFirebaseModule { @@ -37,4 +27,11 @@ public class ReactNativeFirebase_Template_Module extends ReactNativeFirebaseModu super(reactContext, TAG); } + @ReactMethod + public void aMethod() { + // This is just a dummy method. If there are no ReactMethod annotated methods in a module, + // react-native won't even load it, which may lead to confusion as you test a new module. + System.err.println("_Template_::aMethod - this method just logs to system out, then throws"); + throw new Exception(TAG + "::aMethod - Implement real methods now."); + } } diff --git a/scripts/_TEMPLATE_/e2e/_template_.e2e.js b/scripts/_TEMPLATE_/e2e/_template_.e2e.js index 7ce0fcf59f..d8bb85f380 100644 --- a/scripts/_TEMPLATE_/e2e/_template_.e2e.js +++ b/scripts/_TEMPLATE_/e2e/_template_.e2e.js @@ -15,30 +15,9 @@ * */ -describe('_template_()', () => { - describe('namespace', () => { - it('accessible from firebase.app()', () => { - const app = firebase.app(); - should.exist(app._template_); - app._template_().app.should.equal(app); - }); - - // removing as pending if module.options.hasMultiAppSupport = true - xit('supports multiple apps', async () => { - firebase._template_().app.name.should.equal('[DEFAULT]'); - - firebase - ._template_(firebase.app('secondaryFromNative')) - .app.name.should.equal('secondaryFromNative'); - - firebase - .app('secondaryFromNative') - ._template_() - .app.name.should.equal('secondaryFromNative'); - }); - }); - - describe('aMethod()', () => { +describe('_template_()', function () { + + describe('aMethod()', function () { // TODO }); }); diff --git a/scripts/_TEMPLATE_/ios/RNFB_Template_.podspec b/scripts/_TEMPLATE_/ios/RNFB_Template_.podspec deleted file mode 100644 index 1957e5df3c..0000000000 --- a/scripts/_TEMPLATE_/ios/RNFB_Template_.podspec +++ /dev/null @@ -1,22 +0,0 @@ -require 'json' -package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json'))) - -Pod::Spec.new do |s| - s.name = "RNFB_Template_" - s.version = package["version"] - s.description = package["description"] - s.summary = <<-DESC - A well tested feature rich Firebase implementation for React Native, supporting iOS & Android. - DESC - s.homepage = "http://invertase.io/oss/react-native-firebase" - s.license = package['license'] - s.authors = "Invertase Limited" - s.source = { :git => "https://github.com/invertase/react-native-firebase.git", :tag => "v#{s.version}" } - s.social_media_url = 'http://twitter.com/invertaseio' - s.ios.deployment_target = "9.0" - s.source_files = 'RNFB_Template_/**/*.{h,m}' - s.dependency 'React-Core' - s.dependency 'Firebase/Core', '~> 7.0.0' - s.dependency 'RNFBApp' - s.static_framework = true -end diff --git a/scripts/_TEMPLATE_/lib/index.d.ts b/scripts/_TEMPLATE_/lib/index.d.ts index 97d8e17aae..7cf1a3f68e 100644 --- a/scripts/_TEMPLATE_/lib/index.d.ts +++ b/scripts/_TEMPLATE_/lib/index.d.ts @@ -53,7 +53,7 @@ import { ReactNativeFirebase } from '@react-native-firebase/app'; * * @firebase _template_ */ -export namespace _Template_ { +export namespace Firebase_Template_Types { import FirebaseModule = ReactNativeFirebase.FirebaseModule; export interface Statics { @@ -108,8 +108,10 @@ declare const defaultExport: ReactNativeFirebase.FirebaseModuleWithStaticsAndApp >; export const firebase: ReactNativeFirebase.Module & { - auth: typeof defaultExport; - app(name?: string): ReactNativeFirebase.FirebaseApp & { _template_(): _Template_.Module }; + _template_: typeof defaultExport; + app( + name?: string, + ): ReactNativeFirebase.FirebaseApp & { _template_(): Firebase_Template_Types.Module }; }; export default defaultExport; @@ -121,10 +123,13 @@ declare module '@react-native-firebase/app' { namespace ReactNativeFirebase { import FirebaseModuleWithStaticsAndApp = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp; interface Module { - _template_: FirebaseModuleWithStaticsAndApp<_Template_.Module, _Template_.Statics>; + _template_: FirebaseModuleWithStaticsAndApp< + Firebase_Template_Types.Module, + Firebase_Template_Types.Statics + >; } interface FirebaseApp { - _template_(): _Template_.Module; + _template_(): Firebase_Template_Types.Module; } } } diff --git a/scripts/_TEMPLATE_/package.json b/scripts/_TEMPLATE_/package.json index 60a99fcfd3..15f7083b8f 100644 --- a/scripts/_TEMPLATE_/package.json +++ b/scripts/_TEMPLATE_/package.json @@ -22,13 +22,8 @@ "_template_" ], "peerDependencies": { - "@react-native-firebase/app": "*" - }, - "dependencies": { - "@react-native-firebase/app-types": "_VERSION_", "@react-native-firebase/app": "_VERSION_" }, - "gitHead": "2787d4413eb70c61a687c4d6913add6a6a01f582", "publishConfig": { "access": "public" } diff --git a/scripts/create-firebase-module.js b/scripts/create-firebase-module.js index 7437afd397..ebf05fd196 100644 --- a/scripts/create-firebase-module.js +++ b/scripts/create-firebase-module.js @@ -25,7 +25,7 @@ const { version } = require('./../lerna'); function walkDir(dir) { let results = []; const list = readdirSync(dir); - list.forEach(function(file) { + list.forEach(function (file) { file = dir + '/' + file; const stat = statSync(file); if (stat && stat.isDirectory()) { @@ -93,32 +93,21 @@ inquirer return Promise.resolve({ name, nameUpper }); }) .then(({ name, nameUpper }) => { - shelljs.exec( - `lerna add @react-native-firebase/${name} tests && yarn`, - ); + shelljs.exec(`lerna add @react-native-firebase/${name} tests && yarn`); console.log(''); console.log(`The module '${name}' (${nameUpper}) has been created!`); console.log(''); console.log(''); - console.log('TO USE IT ADD TO THE TESTING PROJECT:'); - console.log(''); - console.log(' iOS:'); - console.log(' Add the following to tests/ios/Podfile :'); - console.log( - ` pod 'RNFB${nameUpper}', :path => '../../packages/${name}/ios/RNFB${nameUpper}.podspec', :version => "~> #{rnfb_version}"`, - ); - console.log(''); - console.log(''); - console.log(' Android:'); - console.log(' Add the following to tests/android/settings.gradle :'); - console.log(` include ':@react-native-firebase/${name}'`); - console.log( - ` project(':@react-native-firebase/${name}').projectDir = new File(rootProject.projectDir, './../../packages/${name}/android')`, - ); + console.log('1) ADD IT TO `KNOWN_NAMESPACES` in packages/app/lib/internal/constants.js'); console.log(''); - console.log(' Add the following dependency to tests/android/app/build.gradle :'); - console.log(` implementation project(path: ':@react-native-firebase/${name}')`); + console.log('2) ADD IT TO THE docs:'); + console.log(' - in website/docs/sidebar.yaml'); + console.log(' - in website/scripts/source-reference.js'); + console.log(' - in website/src/templates/utils.ts'); console.log(''); + console.log('3) If the name has hyphens, carefully check:'); + console.log(' - package namespaces in java and package.json and index.d.ts'); + console.log(' - the @firebase tag in index.d.ts (creates docs site reference API links)'); console.log(''); }) .catch(console.error); diff --git a/tests/android/app/build.gradle b/tests/android/app/build.gradle index 94325bcab6..3efd8e4c8c 100644 --- a/tests/android/app/build.gradle +++ b/tests/android/app/build.gradle @@ -140,6 +140,9 @@ dependencies { * TESTING SDKS/LIBRARIES * ------------------------ */ androidTestImplementation(project(path: ':detox')) + + // These are beta, so they are not in the BoM yet. We have to specify the versions explicitly. + androidTestImplementation 'com.google.firebase:firebase-appcheck-debug-testing:16.0.0-beta02' } apply from: file('../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle'); applyNativeModulesAppBuildGradle(project) diff --git a/tests/android/app/src/androidTest/java/com/invertase/testing/DetoxTest.java b/tests/android/app/src/androidTest/java/com/invertase/testing/DetoxTest.java index b6e455b786..9542b6fec1 100644 --- a/tests/android/app/src/androidTest/java/com/invertase/testing/DetoxTest.java +++ b/tests/android/app/src/androidTest/java/com/invertase/testing/DetoxTest.java @@ -8,6 +8,8 @@ import androidx.test.filters.LargeTest; import androidx.test.rule.ActivityTestRule; +import com.google.firebase.appcheck.debug.testing.DebugAppCheckTestHelper; + import com.wix.detox.Detox; import org.junit.Rule; @@ -26,8 +28,40 @@ public class DetoxTest { @Test public void runDetoxTests() { - Detox.runTests(mActivityRule); - dumpCoverageData(); + + try { + // 1) Detox makes it extremely difficult to pass unencoded arguments directly to the instrumentation runner on Android: + // https://github.com/wix/Detox/issues/2933 + // + // 2) AppCheck will only let you set a debug AppCheck token in CI via their test helpers via instrumentation runner args + // https://firebase.google.com/docs/app-check/android/debug-provider#ci + // + // Here we avoid the Detox argument-passing / AppCheck argument-reading difficulty by directly putting the String in. + // + // This is unwanted in nearly all scenarios as it leaks an AppCheck token, but the react-native-firebase test + // project does not have AppCheck set to enforcing, so this is okay for this project. + // + // This has a great potential for leaking your token in a real app that wants to enforce and rely on AppCheck. + Class> testHelperClass = DebugAppCheckTestHelper.class; + Method[] methods = testHelperClass.getDeclaredMethods(); + for (int i = 0; i < methods.length; i++) { + if (methods[i].getName().equals("fromString")) { + Method testHelperMethod = methods[i]; + testHelperMethod.setAccessible(true); + DebugAppCheckTestHelper debugAppCheckTestHelper = + (DebugAppCheckTestHelper)testHelperMethod.invoke(null, "698956B2-187B-49C6-9E25-C3F3530EEBAF"); + debugAppCheckTestHelper.withDebugProvider(() -> { + + // This is the standard Detox androidTest implementation: + Detox.runTests(mActivityRule); + + dumpCoverageData(); + }); + } + } + } catch (Exception e) { + throw new RuntimeException("Unable to force AppCheck debug token: ", e); + } } // If you send '-e coverage' as part of the instrumentation command line, it should dump coverage as the Instrumentation finishes. diff --git a/tests/app.js b/tests/app.js index c957a36609..cf2d91873b 100644 --- a/tests/app.js +++ b/tests/app.js @@ -19,6 +19,7 @@ import '@react-native-firebase/analytics'; import firebase from '@react-native-firebase/app'; import NativeEventEmitter from '@react-native-firebase/app/lib/internal/RNFBNativeEventEmitter'; import '@react-native-firebase/app/lib/utils'; +import '@react-native-firebase/app-check'; import '@react-native-firebase/auth'; import '@react-native-firebase/crashlytics'; import '@react-native-firebase/database'; diff --git a/tests/e2e/.mocharc.js b/tests/e2e/.mocharc.js index 9424325741..c15d4922b3 100644 --- a/tests/e2e/.mocharc.js +++ b/tests/e2e/.mocharc.js @@ -5,13 +5,14 @@ module.exports = { timeout: 720000, reporter: 'spec', slow: 2000, - retries: 2, + retries: 4, bail: true, exit: true, recursive: true, require: 'node_modules/jet/platform/node', spec: [ '../packages/app/e2e/*.e2e.js', + '../packages/app-check/e2e/*.e2e.js', '../packages/analytics/e2e/*.e2e.js', '../packages/auth/e2e/*.e2e.js', '../packages/crashlytics/e2e/*.e2e.js', diff --git a/tests/ios/Podfile b/tests/ios/Podfile index 546f15961a..5e08a34756 100644 --- a/tests/ios/Podfile +++ b/tests/ios/Podfile @@ -12,7 +12,7 @@ Pod::UI.puts "react-native-firebase/tests: Using Firebase SDK version '#{$Fireba #$RNFirebaseAnalyticsWithoutAdIdSupport = true # toggle this to true for the no-ad-tracking Analytics subspec # Versions used below, for quick reference / outdated+upgrade checks -$iOSMinimumDeployVersion = '10.0' +$iOSMinimumDeployVersion = '11.0' platform :ios, $iOSMinimumDeployVersion @@ -35,7 +35,7 @@ target 'testing' do # pod 'FirebaseFirestore', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => $FirebaseSDKVersion # If leveldb auto-inclusion fails and build fails with leveldb symbol conflicts, use this subspec: - pod 'FirebaseFirestore/WithoutLeveldb', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => $FirebaseSDKVersion + #pod 'FirebaseFirestore/WithoutLeveldb', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => $FirebaseSDKVersion # Enables Flipper. # @@ -50,8 +50,19 @@ target 'testing' do installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = $iOSMinimumDeployVersion - config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "" end end + + # This is needed for Apple Silicon (M1) builds https://github.com/facebook/react-native/issues/31941 + installer.aggregate_targets.each do |aggregate_target| + aggregate_target.user_project.native_targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['LIBRARY_SEARCH_PATHS'] = ['$(SDKROOT)/usr/lib/swift', '$(inherited)'] + config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES' + config.build_settings['EXCLUDED_ARCHS'] = 'i386' + end + end + aggregate_target.user_project.save + end end end diff --git a/tests/ios/Podfile.lock b/tests/ios/Podfile.lock index 5325b9b174..911303647b 100644 --- a/tests/ios/Podfile.lock +++ b/tests/ios/Podfile.lock @@ -1,5 +1,350 @@ PODS: + - abseil/algorithm (0.20200225.0): + - abseil/algorithm/algorithm (= 0.20200225.0) + - abseil/algorithm/container (= 0.20200225.0) + - abseil/algorithm/algorithm (0.20200225.0): + - abseil/base/config + - abseil/algorithm/container (0.20200225.0): + - abseil/algorithm/algorithm + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/base (0.20200225.0): + - abseil/base/atomic_hook (= 0.20200225.0) + - abseil/base/base (= 0.20200225.0) + - abseil/base/base_internal (= 0.20200225.0) + - abseil/base/bits (= 0.20200225.0) + - abseil/base/config (= 0.20200225.0) + - abseil/base/core_headers (= 0.20200225.0) + - abseil/base/dynamic_annotations (= 0.20200225.0) + - abseil/base/endian (= 0.20200225.0) + - abseil/base/errno_saver (= 0.20200225.0) + - abseil/base/exponential_biased (= 0.20200225.0) + - abseil/base/log_severity (= 0.20200225.0) + - abseil/base/malloc_internal (= 0.20200225.0) + - abseil/base/periodic_sampler (= 0.20200225.0) + - abseil/base/pretty_function (= 0.20200225.0) + - abseil/base/raw_logging_internal (= 0.20200225.0) + - abseil/base/spinlock_wait (= 0.20200225.0) + - abseil/base/throw_delegate (= 0.20200225.0) + - abseil/base/atomic_hook (0.20200225.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/base (0.20200225.0): + - abseil/base/atomic_hook + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/log_severity + - abseil/base/raw_logging_internal + - abseil/base/spinlock_wait + - abseil/meta/type_traits + - abseil/base/base_internal (0.20200225.0): + - abseil/base/config + - abseil/meta/type_traits + - abseil/base/bits (0.20200225.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/config (0.20200225.0) + - abseil/base/core_headers (0.20200225.0): + - abseil/base/config + - abseil/base/dynamic_annotations (0.20200225.0) + - abseil/base/endian (0.20200225.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/errno_saver (0.20200225.0): + - abseil/base/config + - abseil/base/exponential_biased (0.20200225.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity (0.20200225.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/malloc_internal (0.20200225.0): + - abseil/base/base + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/raw_logging_internal + - abseil/base/periodic_sampler (0.20200225.0): + - abseil/base/core_headers + - abseil/base/exponential_biased + - abseil/base/pretty_function (0.20200225.0) + - abseil/base/raw_logging_internal (0.20200225.0): + - abseil/base/atomic_hook + - abseil/base/config + - abseil/base/core_headers + - abseil/base/log_severity + - abseil/base/spinlock_wait (0.20200225.0): + - abseil/base/base_internal + - abseil/base/core_headers + - abseil/base/errno_saver + - abseil/base/throw_delegate (0.20200225.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/container/common (0.20200225.0): + - abseil/meta/type_traits + - abseil/types/optional + - abseil/container/compressed_tuple (0.20200225.0): + - abseil/utility/utility + - abseil/container/container_memory (0.20200225.0): + - abseil/memory/memory + - abseil/utility/utility + - abseil/container/fixed_array (0.20200225.0): + - abseil/algorithm/algorithm + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/throw_delegate + - abseil/container/compressed_tuple + - abseil/memory/memory + - abseil/container/flat_hash_map (0.20200225.0): + - abseil/algorithm/container + - abseil/container/container_memory + - abseil/container/hash_function_defaults + - abseil/container/raw_hash_map + - abseil/memory/memory + - abseil/container/hash_function_defaults (0.20200225.0): + - abseil/base/config + - abseil/hash/hash + - abseil/strings/strings + - abseil/container/hash_policy_traits (0.20200225.0): + - abseil/meta/type_traits + - abseil/container/hashtable_debug_hooks (0.20200225.0): + - abseil/base/config + - abseil/container/hashtablez_sampler (0.20200225.0): + - abseil/base/base + - abseil/base/core_headers + - abseil/base/exponential_biased + - abseil/container/have_sse + - abseil/debugging/stacktrace + - abseil/memory/memory + - abseil/synchronization/synchronization + - abseil/utility/utility + - abseil/container/have_sse (0.20200225.0) + - abseil/container/inlined_vector (0.20200225.0): + - abseil/algorithm/algorithm + - abseil/base/core_headers + - abseil/base/throw_delegate + - abseil/container/inlined_vector_internal + - abseil/memory/memory + - abseil/container/inlined_vector_internal (0.20200225.0): + - abseil/base/core_headers + - abseil/container/compressed_tuple + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/types/span + - abseil/container/layout (0.20200225.0): + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/strings/strings + - abseil/types/span + - abseil/utility/utility + - abseil/container/raw_hash_map (0.20200225.0): + - abseil/base/throw_delegate + - abseil/container/container_memory + - abseil/container/raw_hash_set + - abseil/container/raw_hash_set (0.20200225.0): + - abseil/base/bits + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/container/common + - abseil/container/compressed_tuple + - abseil/container/container_memory + - abseil/container/hash_policy_traits + - abseil/container/hashtable_debug_hooks + - abseil/container/hashtablez_sampler + - abseil/container/have_sse + - abseil/container/layout + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/utility/utility + - abseil/debugging/debugging_internal (0.20200225.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/errno_saver + - abseil/base/raw_logging_internal + - abseil/debugging/demangle_internal (0.20200225.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/debugging/stacktrace (0.20200225.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/debugging/debugging_internal + - abseil/debugging/symbolize (0.20200225.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/malloc_internal + - abseil/base/raw_logging_internal + - abseil/debugging/debugging_internal + - abseil/debugging/demangle_internal + - abseil/hash/city (0.20200225.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/hash/hash (0.20200225.0): + - abseil/base/core_headers + - abseil/base/endian + - abseil/container/fixed_array + - abseil/hash/city + - abseil/meta/type_traits + - abseil/numeric/int128 + - abseil/strings/strings + - abseil/types/optional + - abseil/types/variant + - abseil/utility/utility + - abseil/memory (0.20200225.0): + - abseil/memory/memory (= 0.20200225.0) + - abseil/memory/memory (0.20200225.0): + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/meta (0.20200225.0): + - abseil/meta/type_traits (= 0.20200225.0) + - abseil/meta/type_traits (0.20200225.0): + - abseil/base/config + - abseil/numeric/int128 (0.20200225.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/strings/internal (0.20200225.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/meta/type_traits + - abseil/strings/str_format (0.20200225.0): + - abseil/strings/str_format_internal + - abseil/strings/str_format_internal (0.20200225.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/numeric/int128 + - abseil/strings/strings + - abseil/types/span + - abseil/strings/strings (0.20200225.0): + - abseil/base/base + - abseil/base/bits + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/base/throw_delegate + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/numeric/int128 + - abseil/strings/internal + - abseil/synchronization/graphcycles_internal (0.20200225.0): + - abseil/base/base + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/malloc_internal + - abseil/base/raw_logging_internal + - abseil/synchronization/kernel_timeout_internal (0.20200225.0): + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/time/time + - abseil/synchronization/synchronization (0.20200225.0): + - abseil/base/atomic_hook + - abseil/base/base + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/malloc_internal + - abseil/base/raw_logging_internal + - abseil/debugging/stacktrace + - abseil/debugging/symbolize + - abseil/synchronization/graphcycles_internal + - abseil/synchronization/kernel_timeout_internal + - abseil/time/time + - abseil/time (0.20200225.0): + - abseil/time/internal (= 0.20200225.0) + - abseil/time/time (= 0.20200225.0) + - abseil/time/internal (0.20200225.0): + - abseil/time/internal/cctz (= 0.20200225.0) + - abseil/time/internal/cctz (0.20200225.0): + - abseil/time/internal/cctz/civil_time (= 0.20200225.0) + - abseil/time/internal/cctz/time_zone (= 0.20200225.0) + - abseil/time/internal/cctz/civil_time (0.20200225.0): + - abseil/base/config + - abseil/time/internal/cctz/time_zone (0.20200225.0): + - abseil/base/config + - abseil/time/internal/cctz/civil_time + - abseil/time/time (0.20200225.0): + - abseil/base/base + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/numeric/int128 + - abseil/strings/strings + - abseil/time/internal/cctz/civil_time + - abseil/time/internal/cctz/time_zone + - abseil/types (0.20200225.0): + - abseil/types/any (= 0.20200225.0) + - abseil/types/bad_any_cast (= 0.20200225.0) + - abseil/types/bad_any_cast_impl (= 0.20200225.0) + - abseil/types/bad_optional_access (= 0.20200225.0) + - abseil/types/bad_variant_access (= 0.20200225.0) + - abseil/types/compare (= 0.20200225.0) + - abseil/types/optional (= 0.20200225.0) + - abseil/types/span (= 0.20200225.0) + - abseil/types/variant (= 0.20200225.0) + - abseil/types/any (0.20200225.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/types/bad_any_cast + - abseil/utility/utility + - abseil/types/bad_any_cast (0.20200225.0): + - abseil/base/config + - abseil/types/bad_any_cast_impl + - abseil/types/bad_any_cast_impl (0.20200225.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/types/bad_optional_access (0.20200225.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/types/bad_variant_access (0.20200225.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/types/compare (0.20200225.0): + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/types/optional (0.20200225.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/types/bad_optional_access + - abseil/utility/utility + - abseil/types/span (0.20200225.0): + - abseil/algorithm/algorithm + - abseil/base/core_headers + - abseil/base/throw_delegate + - abseil/meta/type_traits + - abseil/types/variant (0.20200225.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/types/bad_variant_access + - abseil/utility/utility + - abseil/utility/utility (0.20200225.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/meta/type_traits - boost-for-react-native (1.63.0) + - BoringSSL-GRPC (0.0.7): + - BoringSSL-GRPC/Implementation (= 0.0.7) + - BoringSSL-GRPC/Interface (= 0.0.7) + - BoringSSL-GRPC/Implementation (0.0.7): + - BoringSSL-GRPC/Interface (= 0.0.7) + - BoringSSL-GRPC/Interface (0.0.7) - DoubleConversion (1.1.6) - FBLazyVector (0.64.2) - FBReactNativeSpec (0.64.2): @@ -11,6 +356,9 @@ PODS: - ReactCommon/turbomodule/core (= 0.64.2) - Firebase/Analytics (8.5.0): - Firebase/Core + - Firebase/AppCheck (8.5.0): + - Firebase/CoreOnly + - FirebaseAppCheck (~> 8.5.0-beta) - Firebase/Auth (8.5.0): - Firebase/CoreOnly - FirebaseAuth (~> 8.5.0) @@ -69,6 +417,10 @@ PODS: - GoogleUtilities/Network (~> 7.4) - "GoogleUtilities/NSData+zlib (~> 7.4)" - nanopb (~> 2.30908.0) + - FirebaseAppCheck (8.5.0-beta): + - FirebaseCore (~> 8.0) + - GoogleUtilities/Environment (~> 7.4) + - PromisesObjC (< 3.0, >= 1.2) - FirebaseAuth (8.5.0): - FirebaseCore (~> 8.0) - GoogleUtilities/AppDelegateSwizzler (~> 7.4) @@ -96,15 +448,18 @@ PODS: - FirebaseDynamicLinks (8.5.0): - FirebaseCore (~> 8.0) - FirebaseFirestore (8.5.0): - - FirebaseFirestore/AutodetectLeveldb (= 8.5.0) - - FirebaseFirestore/AutodetectLeveldb (8.5.0): - - FirebaseFirestore/Base - - FirebaseFirestore/WithLeveldb - - FirebaseFirestore/Base (8.5.0) - - FirebaseFirestore/WithLeveldb (8.5.0): - - FirebaseFirestore/Base - - FirebaseFirestore/WithoutLeveldb (8.5.0): - - FirebaseFirestore/Base + - abseil/algorithm (= 0.20200225.0) + - abseil/base (= 0.20200225.0) + - abseil/container/flat_hash_map (= 0.20200225.0) + - abseil/memory (= 0.20200225.0) + - abseil/meta (= 0.20200225.0) + - abseil/strings/strings (= 0.20200225.0) + - abseil/time (= 0.20200225.0) + - abseil/types (= 0.20200225.0) + - FirebaseCore (~> 8.0) + - "gRPC-C++ (~> 1.28.0)" + - leveldb-library (~> 1.22) + - nanopb (~> 2.30908.0) - FirebaseFunctions (8.5.0): - FirebaseCore (~> 8.0) - GTMSessionFetcher/Core (~> 1.5) @@ -182,6 +537,30 @@ PODS: - GoogleUtilities/Logger - GoogleUtilities/UserDefaults (7.5.0): - GoogleUtilities/Logger + - "gRPC-C++ (1.28.2)": + - "gRPC-C++/Implementation (= 1.28.2)" + - "gRPC-C++/Interface (= 1.28.2)" + - "gRPC-C++/Implementation (1.28.2)": + - abseil/container/inlined_vector (= 0.20200225.0) + - abseil/memory/memory (= 0.20200225.0) + - abseil/strings/str_format (= 0.20200225.0) + - abseil/strings/strings (= 0.20200225.0) + - abseil/types/optional (= 0.20200225.0) + - "gRPC-C++/Interface (= 1.28.2)" + - gRPC-Core (= 1.28.2) + - "gRPC-C++/Interface (1.28.2)" + - gRPC-Core (1.28.2): + - gRPC-Core/Implementation (= 1.28.2) + - gRPC-Core/Interface (= 1.28.2) + - gRPC-Core/Implementation (1.28.2): + - abseil/container/inlined_vector (= 0.20200225.0) + - abseil/memory/memory (= 0.20200225.0) + - abseil/strings/str_format (= 0.20200225.0) + - abseil/strings/strings (= 0.20200225.0) + - abseil/types/optional (= 0.20200225.0) + - BoringSSL-GRPC (= 0.0.7) + - gRPC-Core/Interface (= 1.28.2) + - gRPC-Core/Interface (1.28.2) - GTMSessionFetcher/Core (1.6.1) - Jet (0.6.6-0): - React @@ -457,6 +836,10 @@ PODS: - RNFBApp (12.4.0): - Firebase/CoreOnly (= 8.5.0) - React-Core + - RNFBAppCheck (12.4.0): + - Firebase/AppCheck (= 8.5.0) + - React-Core + - RNFBApp - RNFBAuth (12.4.0): - Firebase/Auth (= 8.5.0) - React-Core @@ -511,7 +894,6 @@ DEPENDENCIES: - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) - - FirebaseFirestore/WithoutLeveldb (from `https://github.com/invertase/firestore-ios-sdk-frameworks.git`, tag `8.5.0`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - Jet (from `../node_modules/jet/ios`) - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) @@ -541,6 +923,7 @@ DEPENDENCIES: - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - RNFBAnalytics (from `../../packages/analytics`) - RNFBApp (from `../../packages/app`) + - RNFBAppCheck (from `../../packages/app-check`) - RNFBAuth (from `../../packages/auth`) - RNFBCrashlytics (from `../../packages/crashlytics`) - RNFBDatabase (from `../../packages/database`) @@ -557,16 +940,20 @@ DEPENDENCIES: SPEC REPOS: trunk: + - abseil - boost-for-react-native + - BoringSSL-GRPC - Firebase - FirebaseABTesting - FirebaseAnalytics + - FirebaseAppCheck - FirebaseAuth - FirebaseCore - FirebaseCoreDiagnostics - FirebaseCrashlytics - FirebaseDatabase - FirebaseDynamicLinks + - FirebaseFirestore - FirebaseFunctions - FirebaseInAppMessaging - FirebaseInstallations @@ -577,6 +964,8 @@ SPEC REPOS: - GoogleAppMeasurement - GoogleDataTransport - GoogleUtilities + - "gRPC-C++" + - gRPC-Core - GTMSessionFetcher - leveldb-library - nanopb @@ -590,9 +979,6 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/Libraries/FBLazyVector" FBReactNativeSpec: :path: "../node_modules/react-native/React/FBReactNativeSpec" - FirebaseFirestore: - :git: https://github.com/invertase/firestore-ios-sdk-frameworks.git - :tag: 8.5.0 glog: :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" Jet: @@ -647,6 +1033,8 @@ EXTERNAL SOURCES: :path: "../../packages/analytics" RNFBApp: :path: "../../packages/app" + RNFBAppCheck: + :path: "../../packages/app-check" RNFBAuth: :path: "../../packages/auth" RNFBCrashlytics: @@ -674,26 +1062,24 @@ EXTERNAL SOURCES: Yoga: :path: "../node_modules/react-native/ReactCommon/yoga" -CHECKOUT OPTIONS: - FirebaseFirestore: - :git: https://github.com/invertase/firestore-ios-sdk-frameworks.git - :tag: 8.5.0 - SPEC CHECKSUMS: + abseil: 6c8eb7892aefa08d929b39f9bb108e5367e3228f boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c + BoringSSL-GRPC: 8edf627ee524575e2f8d19d56f068b448eea3879 DoubleConversion: cf9b38bf0b2d048436d9a82ad2abe1404f11e7de FBLazyVector: e686045572151edef46010a6f819ade377dfeb4b FBReactNativeSpec: 25e094945df743fcfa1283399bf9715648bff333 Firebase: ff8c73105b90e33e1dc6c8e5445d7adc2ccdc7c1 FirebaseABTesting: f7cb3fbed1c5bd3e733a79d9955447be3f3b06a5 FirebaseAnalytics: 96325c1e0acbd2bb805c6a613028b1fe599d6a37 + FirebaseAppCheck: 0cced04f86b12f8b72d0a6437a7a4cf76e2ecc07 FirebaseAuth: b152ea261b60eeb9419ae7e5bf34761382b33277 FirebaseCore: 1c1ca72483b59b17050f5b4cec4fb748425a3901 FirebaseCoreDiagnostics: 7bf55d386f9fc690d971b70a582142321a390eb8 FirebaseCrashlytics: 8e7cf678cb149d421198388c6fc3d3acfd266539 FirebaseDatabase: 65c3742ed355f9b9db222036fd154e699ab7d672 FirebaseDynamicLinks: 6e406b3bb669f8c8a63e7254bb63251fa3f88a43 - FirebaseFirestore: a198d266a5e45c599e6e14dc0ae335c571e805dd + FirebaseFirestore: 9aa10de35bb76a5fe40fdf5c858669f0eac88a99 FirebaseFunctions: eb1fedf8eb25c144ef72ff68d78259d79eb29ae5 FirebaseInAppMessaging: ee6cd4397d1e81d34b14f90ec38697dc4ef9fe93 FirebaseInstallations: f2bc590b291d25fb40a9a05b8281c02a881b5117 @@ -705,6 +1091,8 @@ SPEC CHECKSUMS: GoogleAppMeasurement: 8d10c1c470fcb0e5143ed74fddd164f0a0384800 GoogleDataTransport: 85fd18ff3019bb85d3f2c551d04c481dedf71fc9 GoogleUtilities: eea970f4a389963963bffe8d8fabe43540678b9c + "gRPC-C++": 13d8ccef97d5c3c441b7e3c529ef28ebee86fad2 + gRPC-Core: 4afa11bfbedf7cdecd04de535a9e046893404ed5 GTMSessionFetcher: 36689134877faeb055b27dfa4ccc9ceaa42e029e Jet: 84fd0e2e9d49457fc04bc79b5d8857737a01c507 leveldb-library: 50c7b45cbd7bf543c81a468fe557a16ae3db8729 @@ -736,6 +1124,7 @@ SPEC CHECKSUMS: ReactCommon: 149906e01aa51142707a10665185db879898e966 RNFBAnalytics: 527a0a6f0fa696612ff218c2cb81550eba5a2f9b RNFBApp: 2c0c7d92d026ce7593a9e6fded63d1696f8b8d8b + RNFBAppCheck: a491a053ddac4d88e5a0c6b859039e183b78048f RNFBAuth: c8a3e12437fc20472c015aa14bc17b49d37db5ac RNFBCrashlytics: 2ddc6af1205c6dcbc5034772de21221bb8ceeafd RNFBDatabase: c04c1e4141c6b606fbe13fce8146044a8b63343f @@ -750,6 +1139,6 @@ SPEC CHECKSUMS: RNFBStorage: 511b7c79f85da2cb81d79c474f6053ef2f59eb83 Yoga: 575c581c63e0d35c9a83f4b46d01d63abc1100ac -PODFILE CHECKSUM: f25a92eedd54ba32f69cb8b7ec0cbc4ceb364ddd +PODFILE CHECKSUM: c61aa64b498060e6a9470f21629e95b1ece6f524 COCOAPODS: 1.10.2 diff --git a/tests/ios/testing.xcodeproj/project.pbxproj b/tests/ios/testing.xcodeproj/project.pbxproj index f13e2c7997..1f4463b9fe 100644 --- a/tests/ios/testing.xcodeproj/project.pbxproj +++ b/tests/ios/testing.xcodeproj/project.pbxproj @@ -361,6 +361,8 @@ CODE_SIGN_STYLE = Automatic; DEAD_CODE_STRIPPING = NO; DEVELOPMENT_TEAM = YYX2P3XVJ7; + EXCLUDED_ARCHS = i386; + "EXCLUDED_ARCHS[sdk=*]" = i386; HEADER_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/../node_modules/react-native-firebase/Firebase.framework/Headers/**", @@ -373,7 +375,11 @@ "$(inherited)", "@executable_path/Frameworks", ); - LIBRARY_SEARCH_PATHS = "$(inherited)"; + LIBRARY_SEARCH_PATHS = ( + "$(SDKROOT)/usr/lib/swift", + "$(inherited)", + ); + ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = io.invertase.testing; PRODUCT_NAME = testing; @@ -391,6 +397,8 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = YYX2P3XVJ7; + EXCLUDED_ARCHS = i386; + "EXCLUDED_ARCHS[sdk=*]" = i386; HEADER_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/../node_modules/react-native-firebase/Firebase.framework/Headers/**", @@ -403,7 +411,11 @@ "$(inherited)", "@executable_path/Frameworks", ); - LIBRARY_SEARCH_PATHS = "$(inherited)"; + LIBRARY_SEARCH_PATHS = ( + "$(SDKROOT)/usr/lib/swift", + "$(inherited)", + ); + ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = io.invertase.testing; PRODUCT_NAME = testing; diff --git a/tests/ios/testing/AppDelegate.m b/tests/ios/testing/AppDelegate.m index 5e6a1ade42..ef80920909 100644 --- a/tests/ios/testing/AppDelegate.m +++ b/tests/ios/testing/AppDelegate.m @@ -25,6 +25,14 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + + // Install the AppCheck debug provider so we may get tokens on iOS Simulators for testing. + // See https://firebase.google.com/docs/app-check/ios/debug-provider for instructions on configuring a debug token + // This *must* be done before the `[FIRApp configure]` line, so it must be done in AppDelegate for any app + // that wants to enforce AppCheck restrictions on their backend while also doing testing on iOS Simulator. + FIRAppCheckDebugProviderFactory *providerFactory = [[FIRAppCheckDebugProviderFactory alloc] init]; + [FIRAppCheck setAppCheckProviderFactory:providerFactory]; + if ([FIRApp defaultApp] == nil) { [FIRApp configure]; } diff --git a/tests/package.json b/tests/package.json index 9a43c93900..ee842a8780 100644 --- a/tests/package.json +++ b/tests/package.json @@ -9,6 +9,7 @@ "dependencies": { "@react-native-firebase/analytics": "12.4.0", "@react-native-firebase/app": "12.4.0", + "@react-native-firebase/app-check": "12.4.0", "@react-native-firebase/app-types": "6.7.2", "@react-native-firebase/auth": "12.4.0", "@react-native-firebase/crashlytics": "12.4.0", @@ -35,6 +36,7 @@ "jest-circus": "^27.0.6", "jest-environment-node": "^27.0.6", "jet": "^0.6.6-0", + "jsonwebtoken": "^8.5.1", "metro-react-native-babel-preset": "0.66.2", "mocha": "^9.0.3", "nyc": "^15.0.1", @@ -51,7 +53,7 @@ "configurations": { "ios.sim.debug": { "binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/testing.app", - "build": "xcodebuild CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ -workspace ios/testing.xcworkspace -scheme testing -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build -UseModernBuildSystem=YES", + "build": "xcodebuild VALID_ARCHS=\"`uname -m`\" CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ -workspace ios/testing.xcworkspace -scheme testing -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build -UseModernBuildSystem=YES", "type": "ios.simulator", "device": { "type": "iPhone 11" diff --git a/website/scripts/source-reference.js b/website/scripts/source-reference.js index 7bbec91572..e8df4fb7cd 100644 --- a/website/scripts/source-reference.js +++ b/website/scripts/source-reference.js @@ -145,6 +145,8 @@ function moduleNameToFullName(name) { switch (name) { case 'admob': return 'AdMob'; + case 'app-check': + return 'App Check'; case 'analytics': return 'Analytics'; case 'auth': diff --git a/website/src/templates/utils.ts b/website/src/templates/utils.ts index adf724b0f1..0bced9c3b1 100644 --- a/website/src/templates/utils.ts +++ b/website/src/templates/utils.ts @@ -27,6 +27,8 @@ function iconForModule(module: string): string { return '//static.invertase.io/assets/firebase/google-admob.svg'; case 'analytics': return '//static.invertase.io/assets/firebase/analytics.svg'; + case 'app-check': + return '//static.invertase.io/assets/social/firebase-logo.png'; case 'auth': return '//static.invertase.io/assets/firebase/authentication.svg'; case 'firestore':