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) | [![badge](https://img.shields.io/npm/dm/@react-native-firebase/analytics.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@react-native-firebase/analytics) | | [App](/packages/app) | [![badge](https://img.shields.io/npm/dm/@react-native-firebase/app.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@react-native-firebase/app) | +| [AppCheck](/packages/app-check) | [![badge](https://img.shields.io/npm/dm/@react-native-firebase/app-check.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@react-native-firebase/app-check) | | [Authentication](/packages/auth) | [![badge](https://img.shields.io/npm/dm/@react-native-firebase/auth.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@react-native-firebase/auth) | | [Cloud Firestore](/packages/firestore) | [![badge](https://img.shields.io/npm/dm/@react-native-firebase/firestore.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@react-native-firebase/firestore) | | [Cloud Functions](/packages/functions) | [![badge](https://img.shields.io/npm/dm/@react-native-firebase/functions.svg?style=for-the-badge&logo=npm)](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. + + + +This App Check module has built-in support for using the following services as attestation providers: + +- DeviceCheck on iOS +- SafetyNet on Android + +App Check currently works with the following Firebase products: + +- Realtime Database +- Cloud Storage +- Cloud Functions (callable functions) + +The [official Firebase App Check documentation](https://firebase.google.com/docs/app-check) has more information, including about the iOS AppAttest provider, and testing/ CI integration, it is worth a read. + +# Usage + +## Activate + +On iOS if you include the App Check package, it is activated by default. The only configuration possible is the token auto refresh. When you call activate, the provider (DeviceCheck by default) stays the same but the token auto refresh setting will be changed based on the argument provided. + +On Android, App Check is not activated until you call the activate method. The provider is not configurable here either but if your app is "debuggable", then the Debug app check provider will be installed, otherwise the SafetyNet provider will be installed. + +You must call activate prior to calling any firebase back-end services for App Check to function. + +## Automatic Data Collection + +App Check has an "tokenAutoRefreshEnabled" setting. This may cause App Check to attempt a remote App Check token fetch prior to user consent. In certain scenarios, like those that exist in GDPR-compliant apps running for the first time, this may be unwanted. + +If unset, the "tokenAutoRefreshEnabled" setting will defer to the app's "automatic data collection" setting, which may be set in the Info.plist or AndroidManifest.xml + +## Using App Check tokens for non-firebase services + +The [official documentation](https://firebase.google.com/docs/app-check/web/custom-resource) shows how to use `getToken` to access the current App Check token and then verify it in external services. + +## Testing Environments / CI + +App Check may be used in CI environments by following the upstream documentation to configure a debug token shared with your app in the CI environment. + +In certain react-native testing scenarios it may be difficult to access the shared secret, but the react-native-firebase testing app for e2e testing does successfully fetch App Check tokens via: + +- including the App Check debug test helper in the test app, along with a change to `DetoxTest` for Android +- by setting an environment variable and initializing the debug provider before firebase configure in `AppDelegate.m` for iOS. diff --git a/docs/app/usage.md b/docs/app/usage.md index 1c012eb27c..3cd0265396 100644 --- a/docs/app/usage.md +++ b/docs/app/usage.md @@ -21,6 +21,7 @@ for manually initializing secondary Firebase app instances. Currently, the native Firebase SDKs only provide functionality for creating secondary apps on the following services: +- [AppCheck](/app-check/usage). - [Authentication](/auth/usage). - [Realtime Database](/database/usage). - [Cloud Firestore](/firestore/usage). diff --git a/docs/auth/usage/index.md b/docs/auth/usage/index.md index 7c65b65024..b5a15f3513 100644 --- a/docs/auth/usage/index.md +++ b/docs/auth/usage/index.md @@ -3,7 +3,7 @@ title: Authentication description: Installation and getting started with Authentication. icon: //static.invertase.io/assets/firebase/authentication.svg next: /auth/social-auth -previous: /analytics/screen-tracking +previous: /app-check/usage --- # Installation diff --git a/docs/releases/index.md b/docs/releases/index.md index e8765482ad..82e632ce4b 100644 --- a/docs/releases/index.md +++ b/docs/releases/index.md @@ -15,9 +15,9 @@ From version `v6.5.0` until `10.0.0`; all React Native Firebase packages were in | Package | | | | ---------------------- | :------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------: | -| AdMob | ![hide:badge](https://img.shields.io/npm/v/@react-native-firebase/admob.svg?style=for-the-badge&logo=npm) | [View Release Notes »](https://github.com/invertase/react-native-firebase/tree/master/packages/admob/CHANGELOG.md) | | Analytics | ![hide:badge](https://img.shields.io/npm/v/@react-native-firebase/analytics.svg?style=for-the-badge&logo=npm) | [View Release Notes »](https://github.com/invertase/react-native-firebase/tree/master/packages/analytics/CHANGELOG.md) | | App | ![hide:badge](https://img.shields.io/npm/v/@react-native-firebase/app.svg?style=for-the-badge&logo=npm) | [View Release Notes »](https://github.com/invertase/react-native-firebase/tree/master/packages/app/CHANGELOG.md) | +| AppCheck | ![hide:badge](https://img.shields.io/npm/v/@react-native-firebase/app-check.svg?style=for-the-badge&logo=npm) | [View Release Notes »](https://github.com/invertase/react-native-firebase/tree/master/packages/app-check/CHANGELOG.md) | | Authentication | ![hide:badge](https://img.shields.io/npm/v/@react-native-firebase/auth.svg?style=for-the-badge&logo=npm) | [View Release Notes »](https://github.com/invertase/react-native-firebase/tree/master/packages/auth/CHANGELOG.md) | | Cloud Firestore | ![hide:badge](https://img.shields.io/npm/v/@react-native-firebase/firestore.svg?style=for-the-badge&logo=npm) | [View Release Notes »](https://github.com/invertase/react-native-firebase/tree/master/packages/firestore/CHANGELOG.md) | | Cloud Functions | ![hide:badge](https://img.shields.io/npm/v/@react-native-firebase/functions.svg?style=for-the-badge&logo=npm) | [View Release Notes »](https://github.com/invertase/react-native-firebase/tree/master/packages/functions/CHANGELOG.md) | diff --git a/docs/sidebar.yaml b/docs/sidebar.yaml index 0de68ff22a..51897590ca 100644 --- a/docs/sidebar.yaml +++ b/docs/sidebar.yaml @@ -23,6 +23,10 @@ - - Building an Analytics Funnel - 'https://blog.theodo.com/2018/01/building-google-analytics-funnel-firebase-react-native' - '//static.invertase.io/assets/firebase/analytics.svg' +- - App Check + - - - Usage + - '/app-check/usage' + - '//static.invertase.io/assets/social/firebase-logo.png' - - Authentication - - - Usage - '/auth/usage' diff --git a/package.json b/package.json index 742a4960d0..970dbd93fd 100644 --- a/package.json +++ b/package.json @@ -34,11 +34,11 @@ "tests:android:test:jacoco-report": "cd tests/android && ./gradlew jacocoAndroidTestReport", "tests:ios:build": "cd tests && ./node_modules/.bin/detox build --configuration ios.sim.debug", "tests:ios:build-release": "cd tests && ./node_modules/.bin/detox build --configuration ios.sim.release", - "tests:ios:test": "cd tests && ./node_modules/.bin/detox test --configuration ios.sim.debug --loglevel warn", - "tests:ios:test:debug": "cd tests && ./node_modules/.bin/detox test --configuration ios.sim.debug --loglevel warn --inspect", - "tests:ios:test-reuse": "cd tests && ./node_modules/.bin/detox test --configuration ios.sim.debug --reuse --loglevel warn", - "tests:ios:test-cover": "cd tests && ./node_modules/.bin/nyc ./node_modules/.bin/detox test --configuration ios.sim.debug --loglevel warn", - "tests:ios:test-cover-reuse": "cd tests && node_modules/.bin/nyc ./node_modules/.bin/detox test --configuration ios.sim.debug --reuse --loglevel warn", + "tests:ios:test": "cd tests && SIMCTL_CHILD_FIRAAppCheckDebugToken=698956B2-187B-49C6-9E25-C3F3530EEBAF ./node_modules/.bin/detox test --configuration ios.sim.debug --loglevel warn", + "tests:ios:test:debug": "cd tests && SIMCTL_CHILD_FIRAAppCheckDebugToken=698956B2-187B-49C6-9E25-C3F3530EEBAF ./node_modules/.bin/detox test --configuration ios.sim.debug --loglevel warn --inspect", + "tests:ios:test-reuse": "cd tests && SIMCTL_CHILD_FIRAAppCheckDebugToken=\"698956B2-187B-49C6-9E25-C3F3530EEBAF\" ./node_modules/.bin/detox test --configuration ios.sim.debug --reuse --loglevel warn", + "tests:ios:test-cover": "cd tests && SIMCTL_CHILD_FIRAAppCheckDebugToken=698956B2-187B-49C6-9E25-C3F3530EEBAF ./node_modules/.bin/nyc ./node_modules/.bin/detox test --configuration ios.sim.debug --loglevel warn", + "tests:ios:test-cover-reuse": "cd tests && SIMCTL_CHILD_FIRAAppCheckDebugToken=698956B2-187B-49C6-9E25-C3F3530EEBAF node_modules/.bin/nyc ./node_modules/.bin/detox test --configuration ios.sim.debug --reuse --loglevel warn", "tests:ios:pod:install": "cd tests && cd ios && rm -rf ReactNativeFirebaseDemo.xcworkspace && rm -f Podfile.lock && pod install --repo-update && cd ..", "format:markdown": "prettier --write \"docs/**/*.md\"" }, diff --git a/packages/app-check/.npmignore b/packages/app-check/.npmignore new file mode 100644 index 0000000000..d9fa30e5a5 --- /dev/null +++ b/packages/app-check/.npmignore @@ -0,0 +1,65 @@ +# Built application files +android/*/build/ + +# Crashlytics configuations +android/com_crashlytics_export_strings.xml + +# Local configuration file (sdk path, etc) +android/local.properties + +# Gradle generated files +android/.gradle/ + +# Signing files +android/.signing/ + +# User-specific configurations +android/.idea/gradle.xml +android/.idea/libraries/ +android/.idea/workspace.xml +android/.idea/tasks.xml +android/.idea/.name +android/.idea/compiler.xml +android/.idea/copyright/profiles_settings.xml +android/.idea/encodings.xml +android/.idea/misc.xml +android/.idea/modules.xml +android/.idea/scopes/scope_settings.xml +android/.idea/vcs.xml +android/*.iml + +# Xcode +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 +*.xcuserstate +ios/Pods +ios/build +*project.xcworkspace* +*xcuserdata* + +# OS-specific files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.dbandroid/gradle +android/gradlew +android/build +android/gradlew.bat +android/gradle/ + +.idea +coverage +yarn.lock +e2e/ +.github +.vscode +.nyc_output +android/.settings +*.coverage.json +.circleci +.eslintignore diff --git a/packages/app-check/LICENSE b/packages/app-check/LICENSE new file mode 100644 index 0000000000..ef3ed44f06 --- /dev/null +++ b/packages/app-check/LICENSE @@ -0,0 +1,32 @@ +Apache-2.0 License +------------------ + +Copyright (c) 2016-present Invertase Limited & Contributors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this library except in compliance with the License. + +You may obtain a copy of the Apache-2.0 License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +Creative Commons Attribution 3.0 License +---------------------------------------- + +Copyright (c) 2016-present Invertase Limited & Contributors + +Documentation and other instructional materials provided for this project +(including on a separate documentation repository or it's documentation website) are +licensed under the Creative Commons Attribution 3.0 License. Code samples/blocks +contained therein are licensed under the Apache License, Version 2.0 (the "License"), as above. + +You may obtain a copy of the Creative Commons Attribution 3.0 License at + + https://creativecommons.org/licenses/by/3.0/ diff --git a/packages/app-check/README.md b/packages/app-check/README.md new file mode 100644 index 0000000000..3eceee080d --- /dev/null +++ b/packages/app-check/README.md @@ -0,0 +1,55 @@ +

+ +
+
+

React Native Firebase - AppCheck

+

+ +

+ Coverage + NPM downloads + NPM version + License + Maintained with Lerna +

+ +

+ Chat on Discord + Follow on Twitter + Follow on Facebook +

+ +--- + +AppCheck description. + +[> Learn More](https://firebase.google.com/products/app-check/) + +## Installation + +Requires `@react-native-firebase/app` to be installed. + +```bash +yarn add @react-native-firebase/app-check +``` + +## Documentation + +- [Guides](#TODO) +- [Installation](#TODO) +- [Reference](#TODO) + +## License + +- See [LICENSE](/LICENSE) + +--- + +

+ +

+ 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 @@ + + + + + diff --git a/packages/app-check/android/settings.gradle b/packages/app-check/android/settings.gradle new file mode 100644 index 0000000000..928655e811 --- /dev/null +++ b/packages/app-check/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = '@react-native-firebase_appCheck' diff --git a/packages/app-check/android/src/main/AndroidManifest.xml b/packages/app-check/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..452b309ee9 --- /dev/null +++ b/packages/app-check/android/src/main/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/app-check/android/src/main/java/io/invertase/firebase/appcheck/ReactNativeFirebaseAppCheckModule.java b/packages/app-check/android/src/main/java/io/invertase/firebase/appcheck/ReactNativeFirebaseAppCheckModule.java new file mode 100644 index 0000000000..d8e8450aec --- /dev/null +++ b/packages/app-check/android/src/main/java/io/invertase/firebase/appcheck/ReactNativeFirebaseAppCheckModule.java @@ -0,0 +1,86 @@ +package io.invertase.firebase.appcheck; + +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.util.Log; + +import com.google.android.gms.tasks.Tasks; + +import com.google.firebase.FirebaseApp; +import com.google.firebase.appcheck.FirebaseAppCheck; +import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory; +import com.google.firebase.appcheck.safetynet.SafetyNetAppCheckProviderFactory; + +import com.facebook.react.bridge.*; +import io.invertase.firebase.common.ReactNativeFirebaseModule; + + +public class ReactNativeFirebaseAppCheckModule extends ReactNativeFirebaseModule { + private static final String TAG = "AppCheck"; + + ReactNativeFirebaseAppCheckModule(ReactApplicationContext reactContext) { + super(reactContext, TAG); + } + + @ReactMethod + public void activate(String appName, String siteKeyProvider, boolean isTokenAutoRefreshEnabled, Promise promise) { + try { + FirebaseAppCheck firebaseAppCheck = FirebaseAppCheck.getInstance(); + firebaseAppCheck.setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled); + boolean isDebuggable = false; + PackageManager pm = getContext().getPackageManager(); + if (pm != null) { + isDebuggable = (0 != (pm.getApplicationInfo(getContext().getPackageName(), 0).flags & ApplicationInfo.FLAG_DEBUGGABLE)); + } + + if (isDebuggable) { + firebaseAppCheck.installAppCheckProviderFactory(DebugAppCheckProviderFactory.getInstance()); + } else { + firebaseAppCheck.installAppCheckProviderFactory(SafetyNetAppCheckProviderFactory.getInstance()); + } + } catch (Exception e) { + rejectPromiseWithCodeAndMessage(promise, "unknown", "internal-error", "unimplemented"); + return; + } + promise.resolve(null); + } + + @ReactMethod + public void setTokenAutoRefreshEnabled(String appName, boolean isTokenAutoRefreshEnabled) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAppCheck.getInstance(firebaseApp).setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled); + } + + @ReactMethod + public void getToken(String appName, boolean forceRefresh, Promise promise) { + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + Tasks.call(getExecutor(), () -> { + return Tasks.await(FirebaseAppCheck.getInstance(firebaseApp).getAppCheckToken(forceRefresh)); + }) + .addOnCompleteListener(getExecutor(), (task) -> { + if (task.isSuccessful()) { + promise.resolve(task.getResult().getToken()); + } else { + Log.e(TAG, "RNFB: Unknown error while fetching AppCheck token " + task.getException().getMessage()); + rejectPromiseWithCodeAndMessage(promise, "token-error", task.getException().getMessage()); + } + }); + } +} diff --git a/packages/app-check/android/src/main/java/io/invertase/firebase/appcheck/ReactNativeFirebaseAppCheckPackage.java b/packages/app-check/android/src/main/java/io/invertase/firebase/appcheck/ReactNativeFirebaseAppCheckPackage.java new file mode 100644 index 0000000000..fc2f94319a --- /dev/null +++ b/packages/app-check/android/src/main/java/io/invertase/firebase/appcheck/ReactNativeFirebaseAppCheckPackage.java @@ -0,0 +1,42 @@ +package io.invertase.firebase.appcheck; + +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@SuppressWarnings("unused") +public class ReactNativeFirebaseAppCheckPackage implements ReactPackage { + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + List modules = new ArrayList<>(); + modules.add(new ReactNativeFirebaseAppCheckModule(reactContext)); + return modules; + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } +} diff --git a/packages/app-check/e2e/appcheck.e2e.js b/packages/app-check/e2e/appcheck.e2e.js new file mode 100644 index 0000000000..b90f0e2adf --- /dev/null +++ b/packages/app-check/e2e/appcheck.e2e.js @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +const jwt = require('jsonwebtoken'); + +describe('appCheck()', function () { + describe('setTokenAutoRefresh())', function () { + it('should set token refresh', function () { + firebase.appCheck().setTokenAutoRefreshEnabled(false); + }); + }); + describe('getToken())', function () { + it('token fetch attempt should work', async function () { + // Our tests configure a debug provider with shared secret so we should get a valid token + const token = await firebase.appCheck().getToken(true); + token.should.not.equal(''); + const decodedToken = jwt.decode(token); + decodedToken.aud[1].should.equal('projects/react-native-firebase-testing'); + if (decodedToken.exp < Date.now()) { + Promise.reject('Token already expired'); + } + }); + }); + describe('activate())', function () { + it('should activate with default provider and default token refresh', async function () { + try { + await firebase.appCheck().activate('ignored', true); + } catch (e) { + return Promise.reject(e); + } + }); + // Dynamic providers are not possible on iOS, so the debug provider is always working + android.it('token fetch attempt should work but fail attestation', async function () { + try { + // Activating on Android clobbers the shared secret in the debug provider shared secret, should fail now + await firebase.appCheck().getToken(true); + return Promise.reject('Should have thrown after resetting shared secret on debug provider'); + } catch (e) { + e.message.should.containEql('[appCheck/token-error]'); + e.message.should.containEql('App attestation failed'); + return Promise.resolve(); + } + }); + }); +}); diff --git a/packages/app-check/ios/RNFBAppCheck.xcodeproj/project.pbxproj b/packages/app-check/ios/RNFBAppCheck.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..e27612c683 --- /dev/null +++ b/packages/app-check/ios/RNFBAppCheck.xcodeproj/project.pbxproj @@ -0,0 +1,349 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 48; + objects = { + +/* Begin PBXBuildFile section */ + 2744B98621F45429004F8E3F /* RNFBAppCheckModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 2744B98521F45429004F8E3F /* RNFBAppCheckModule.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 2744B98021F45429004F8E3F /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 2744B98221F45429004F8E3F /* libRNFBAppCheck.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNFBAppCheck.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 2744B98421F45429004F8E3F /* RNFBAppCheckModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNFBAppCheckModule.h; path = RNFBAppCheck/RNFBAppCheckModule.h; sourceTree = SOURCE_ROOT; }; + 2744B98521F45429004F8E3F /* RNFBAppCheckModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = RNFBAppCheckModule.m; path = RNFBAppCheck/RNFBAppCheckModule.m; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2744B97F21F45429004F8E3F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2744B97521F452B8004F8E3F /* Products */ = { + isa = PBXGroup; + children = ( + 2744B98221F45429004F8E3F /* libRNFBAppCheck.a */, + ); + name = Products; + sourceTree = ""; + }; + 2744B98321F45429004F8E3F /* RNFBAppCheck */ = { + isa = PBXGroup; + children = ( + 2744B9A121F48736004F8E3F /* converters */, + 2744B98C21F45C64004F8E3F /* common */, + 2744B98421F45429004F8E3F /* RNFBAppCheckModule.h */, + 2744B98521F45429004F8E3F /* RNFBAppCheckModule.m */, + ); + path = RNFBAppCheck; + sourceTree = ""; + }; + 3323F52AAFE26B7384BE4DE3 = { + isa = PBXGroup; + children = ( + 2744B98321F45429004F8E3F /* RNFBAppCheck */, + 2744B97521F452B8004F8E3F /* Products */, + ); + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 2744B98121F45429004F8E3F /* RNFBAppCheck */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2744B98821F45429004F8E3F /* Build configuration list for PBXNativeTarget "RNFBAppCheck" */; + buildPhases = ( + 2744B97E21F45429004F8E3F /* Sources */, + 2744B97F21F45429004F8E3F /* Frameworks */, + 2744B98021F45429004F8E3F /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RNFBAppCheck; + productName = RNFBAppCheck; + productReference = 2744B98221F45429004F8E3F /* libRNFBAppCheck.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 3323F95273A95DB34F55C6D7 /* Project object */ = { + isa = PBXProject; + attributes = { + CLASSPREFIX = RNFBAppCheck; + LastUpgradeCheck = 1010; + ORGANIZATIONNAME = Invertase; + TargetAttributes = { + 2744B98121F45429004F8E3F = { + CreatedOnToolsVersion = 10.1; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 3323F1C5716BA966BBBB95A4 /* Build configuration list for PBXProject "RNFBAppCheck" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 3323F52AAFE26B7384BE4DE3; + productRefGroup = 2744B97521F452B8004F8E3F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2744B98121F45429004F8E3F /* RNFBAppCheck */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 2744B97E21F45429004F8E3F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2744B98621F45429004F8E3F /* RNFBAppCheckModule.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 2744B98921F45429004F8E3F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 2744B98A21F45429004F8E3F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 3323F77D701E1896E6D239CF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "${BUILT_PRODUCTS_DIR}/**", + "${SRCROOT}/../../../ios/Firebase/**", + "$(FIREBASE_SEARCH_PATH)/Firebase/**", + "$(SRCROOT)/../../../ios/Pods/FirebaseAppCheck/Frameworks", + "$(SRCROOT)/../../../tests/ios/Pods/FirebaseAppCheck/Frameworks", + ); + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(REACT_SEARCH_PATH)/React/**", + "$(SRCROOT)/../../react-native/React/**", + "$(SRCROOT)/../../react-native-firebase/ios/**", + "$(FIREBASE_SEARCH_PATH)/Firebase/**", + "${SRCROOT}/../../../ios/Firebase/**", + "${SRCROOT}/../../../ios/Pods/Headers/Public/**", + "${SRCROOT}/../../../tests/ios/Pods/Headers/Public/**", + "$(SRCROOT)/../../../node_modules/react-native/React/**", + "$(SRCROOT)/../../../node_modules/react-native-firebase/ios/**", + "$(SRCROOT)/../../../packages/app/ios/**", + ); + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + MACH_O_TYPE = staticlib; + OTHER_LDFLAGS = "$(inherited)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 3323F7E33E1559A2B9826720 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "${BUILT_PRODUCTS_DIR}/**", + "${SRCROOT}/../../../ios/Firebase/**", + "$(FIREBASE_SEARCH_PATH)/Firebase/**", + "$(SRCROOT)/../../../ios/Pods/FirebaseAppCheck/Frameworks", + ); + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(REACT_SEARCH_PATH)/React/**", + "$(SRCROOT)/../../react-native/React/**", + "$(SRCROOT)/../../react-native-firebase/ios/**", + "$(FIREBASE_SEARCH_PATH)/Firebase/**", + "${SRCROOT}/../../../ios/Firebase/**", + "${SRCROOT}/../../../ios/Pods/Headers/Public/**", + "${SRCROOT}/../../../tests/ios/Pods/Headers/Public/**", + "$(SRCROOT)/../../../node_modules/react-native/React/**", + "$(SRCROOT)/../../../node_modules/react-native-firebase/ios/**", + "$(SRCROOT)/../../../packages/app/ios/**", + ); + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + MACH_O_TYPE = staticlib; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = "$(inherited)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2744B98821F45429004F8E3F /* Build configuration list for PBXNativeTarget "RNFBAppCheck" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2744B98921F45429004F8E3F /* Debug */, + 2744B98A21F45429004F8E3F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3323F1C5716BA966BBBB95A4 /* Build configuration list for PBXProject "RNFBAppCheck" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3323F7E33E1559A2B9826720 /* Debug */, + 3323F77D701E1896E6D239CF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 3323F95273A95DB34F55C6D7 /* Project object */; +} diff --git a/packages/app-check/ios/RNFBAppCheck.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/app-check/ios/RNFBAppCheck.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..919434a625 --- /dev/null +++ b/packages/app-check/ios/RNFBAppCheck.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/app-check/ios/RNFBAppCheck.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/app-check/ios/RNFBAppCheck.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000..18d981003d --- /dev/null +++ b/packages/app-check/ios/RNFBAppCheck.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/app-check/ios/RNFBAppCheck.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/app-check/ios/RNFBAppCheck.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000000..0c67376eba --- /dev/null +++ b/packages/app-check/ios/RNFBAppCheck.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/app-check/ios/RNFBAppCheck.xcodeproj/xcshareddata/IDETemplateMacros.plist b/packages/app-check/ios/RNFBAppCheck.xcodeproj/xcshareddata/IDETemplateMacros.plist new file mode 100644 index 0000000000..63f0a6e5dd --- /dev/null +++ b/packages/app-check/ios/RNFBAppCheck.xcodeproj/xcshareddata/IDETemplateMacros.plist @@ -0,0 +1,24 @@ + + + + + FILEHEADER + +/** + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + diff --git a/packages/app-check/ios/RNFBAppcheck/RNFBAppCheckModule.h b/packages/app-check/ios/RNFBAppcheck/RNFBAppCheckModule.h new file mode 100644 index 0000000000..bd8fe9a23c --- /dev/null +++ b/packages/app-check/ios/RNFBAppcheck/RNFBAppCheckModule.h @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import + +#import + +@interface RNFBAppCheckModule : NSObject + +@end diff --git a/packages/app-check/ios/RNFBAppcheck/RNFBAppCheckModule.m b/packages/app-check/ios/RNFBAppcheck/RNFBAppCheckModule.m new file mode 100644 index 0000000000..2aebe3a5a0 --- /dev/null +++ b/packages/app-check/ios/RNFBAppcheck/RNFBAppCheckModule.m @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import +#import + +#import "RNFBAppCheckModule.h" +#import "RNFBApp/RNFBSharedUtils.h" + +#import "FirebaseAppCheck/FIRAppCheck.h" + + +@implementation RNFBAppCheckModule +#pragma mark - +#pragma mark Module Setup + + RCT_EXPORT_MODULE(); + + - (dispatch_queue_t)methodQueue { + return dispatch_get_main_queue(); + } + +#pragma mark - +#pragma mark Firebase AppCheck Methods + +RCT_EXPORT_METHOD(activate: + (FIRApp *) firebaseApp + :(nonnull NSString *) siteKeyOrProvider + :(BOOL) isTokenAutoRefreshEnabled +) { + + // From SDK docs: + // NOTE: Make sure to call this method before FirebaseApp.configure(). + // If this method is called after configuring Firebase, the changes will not take effect. + + // So in react-native-firebase we will only use this to set the isTokenAutoRefreshEnabled parameter, + // but if AppCheck is included on iOS it wlil be active with DeviceCheckProviderFactory + + FIRAppCheck* appCheck = [FIRAppCheck appCheckWithApp:firebaseApp]; + appCheck.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled; +} + +RCT_EXPORT_METHOD(setTokenAutoRefreshEnabled: + (FIRApp *) firebaseApp + :(BOOL) isTokenAutoRefreshEnabled +) { + FIRAppCheck* appCheck = [FIRAppCheck appCheckWithApp:firebaseApp]; + appCheck.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled; +} + +RCT_EXPORT_METHOD(getToken: + (FIRApp *) firebaseApp + :(BOOL) forceRefresh + :(RCTPromiseResolveBlock)resolve + :(RCTPromiseRejectBlock)reject +) { + FIRAppCheck* appCheck = [FIRAppCheck appCheckWithApp: firebaseApp]; + [appCheck tokenForcingRefresh:NO + completion:^(FIRAppCheckToken * _Nullable token, + NSError * _Nullable error) { + if (error != nil) { + // Handle any errors if the token was not retrieved. + DLog(@"Unable to retrieve App Check token: %@", error); + [RNFBSharedUtils rejectPromiseWithUserInfo:reject userInfo:(NSMutableDictionary *) @{ + @"code": @"token-error", + @"message": [error localizedDescription], + }]; + return; + } + if (token == nil) { + DLog(@"Unable to retrieve App Check token."); + [RNFBSharedUtils rejectPromiseWithUserInfo:reject userInfo:(NSMutableDictionary *) @{ + @"code": @"token-null", + @"message": @"no token fetched", + }]; + return; + } + + resolve(token.token); + }]; +} + +// TODO +// - set up DeviceCheckProvider and Debug provider + // FIRAppCheckDebugProviderFactory *providerFactory = + // [[FIRAppCheckDebugProviderFactory alloc] init]; + // [FIRAppCheck setAppCheckProviderFactory:providerFactory]; + +// - allow disable via firebase.json to override automatic data collection selection via +// FirebaseAppCheckTokenAutoRefreshEnabled is the plist value to put to NO or YES + +// Write a custom provider factory, and allow the AppAttest provider + +@end diff --git a/packages/app-check/lib/index.d.ts b/packages/app-check/lib/index.d.ts new file mode 100644 index 0000000000..125b5dce63 --- /dev/null +++ b/packages/app-check/lib/index.d.ts @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { ReactNativeFirebase } from '@react-native-firebase/app'; + +/** + * Firebase App Check package for React Native. + * + * #### Example 1 + * + * Access the firebase export from the `appCheck` package: + * + * ```js + * import { firebase } from '@react-native-firebase/app-check'; + * + * // firebase.appCheck().X + * ``` + * + * #### Example 2 + * + * Using the default export from the `appCheck` package: + * + * ```js + * import appCheck from '@react-native-firebase/app-check'; + * + * // appCheck().X + * ``` + * + * #### Example 3 + * + * Using the default export from the `app` package: + * + * ```js + * import firebase from '@react-native-firebase/app'; + * import '@react-native-firebase/app-check'; + * + * // firebase.appCheck().X + * ``` + * + * @firebase app-check + */ +export namespace FirebaseAppCheckTypes { + import FirebaseModule = ReactNativeFirebase.FirebaseModule; + + /** + * An App Check provider. This can be either the built-in reCAPTCHA provider + * or a custom provider. For more on custom providers, see + * https://firebase.google.com/docs/app-check/web-custom-provider + */ + export interface AppCheckProvider { + /** + * Returns an AppCheck token. + */ + getToken(): Promise; + } + + /** + * Result returned by `getToken()`. + */ + interface AppCheckTokenResult { + /** + * The token string in JWT format. + */ + readonly token: string; + } + /** + * The token returned from an `AppCheckProvider`. + */ + export interface AppCheckToken { + /** + * The token string in JWT format. + */ + readonly token: string; + /** + * The local timestamp after which the token will expire. + */ + readonly expireTimeMillis: number; + } + + // eslint-disable-next-line @typescript-eslint/no-empty-interface + export interface Statics { + // firebase.appCheck.* static props go here + } + + /** + * The Firebase App Check service is available for the default app or a given app. + * + * #### Example 1 + * + * Get the appCheck instance for the **default app**: + * + * ```js + * const appCheckForDefaultApp = firebase.appCheck(); + * ``` + * + * #### Example 2 + * + * Get the appCheck instance for a **secondary app**: + *˚ + * ```js + * const otherApp = firebase.app('otherApp'); + * const appCheckForOtherApp = firebase.appCheck(otherApp); + * ``` + * + */ + export class Module extends FirebaseModule { + /** + * Activate App Check + * On iOS App Check is activated with DeviceCheck provider simply by including the module, but calling this does no harm. + * On Android you must call this and it will install the SafetyNet provider in release builds, the Debug provider if debuggable. + * On both platforms you may use this method to alter the token refresh setting after startup. + * On iOS if you want to set a specific AppCheckProviderFactory (for instance to FIRAppCheckDebugProviderFactory or + * FIRAppAttestProvider) you must manually do that in your AppDelegate.m prior to calling [FIRApp configure] + * + * @param siteKeyOrProvider - This is ignored, Android uses DebugProviderFactory if the app is debuggable (https://firebase.google.com/docs/app-check/android/debug-provider) + * Android uses SafetyNetProviderFactory for release builds. + * iOS uses DeviceCheckProviderFactory by default unless altered in AppDelegate.m manually + * @param isTokenAutoRefreshEnabled - If true, enables SDK to automatically + * refresh AppCheck token as needed. If undefined, the value will default + * to the value of `app.automaticDataCollectionEnabled`. That property + * defaults to false and can be set in the app config. + */ + activate( + siteKeyOrProvider: string | AppCheckProvider, + isTokenAutoRefreshEnabled?: boolean, + ): Promise; + + /** + * Alter the token auto refresh setting. By default it will take the value of automaticDataCollectionEnabled from Info.plist / AndroidManifest.xml + * @param isTokenAutoRefreshEnabled - If true, the SDK automatically + * refreshes App Check tokens as needed. This overrides any value set + * during `activate()` or taken by default from automaticDataCollectionEnabled in plist / android manifest + */ + setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled: boolean): void; + + /** + * Requests Firebase App Check token. + * This method should only be used if you need to authorize requests to a non-Firebase backend. + * Requests to Firebase backend are authorized automatically if configured. + * + * @param forceRefresh - If true, a new Firebase App Check token is requested and the token cache is ignored. + * If false, the cached token is used if it exists and has not expired yet. + * In most cases, false should be used. True should only be used if the server explicitly returns an error, indicating a revoked token. + */ + getToken(forceRefresh?: boolean): Promise; + + /** + * Registers a listener to changes in the token state. There can be more + * than one listener registered at the same time for one or more + * App Check instances. The listeners call back on the UI thread whenever + * the current token associated with this App Check instance changes. + * + * @returns A function that unsubscribes this listener. + */ + // TODO there is a great deal of Observer / PartialObserver typing to carry-in + // onTokenChanged(observer: PartialObserver): () => void; + + /** + * TODO implement token listener for android. + * + * Registers a listener to changes in the token state. There can be more + * than one listener registered at the same time for one or more + * App Check instances. The listeners call back on the UI thread whenever + * the current token associated with this App Check instance changes. + * + * Token listeners do not exist in the native SDK for iOS, no token change events will be emitted on that platform. + * This is not yet implemented on Android, no token change events will be emitted until implemented. + * + * @returns A function that unsubscribes this listener. + */ + // onTokenChanged( + // onNext: (tokenResult: AppCheckTokenResult) => void, + // onError?: (error: Error) => void, + // onCompletion?: () => void, + // ): () => void; + } +} + +declare const defaultExport: ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< + FirebaseAppCheckTypes.Module, + FirebaseAppCheckTypes.Statics +>; + +export const firebase: ReactNativeFirebase.Module & { + appCheck: typeof defaultExport; + app( + name?: string, + ): ReactNativeFirebase.FirebaseApp & { appCheck(): FirebaseAppCheckTypes.Module }; +}; + +export default defaultExport; + +/** + * Attach namespace to `firebase.` and `FirebaseApp.`. + */ +declare module '@react-native-firebase/app' { + namespace ReactNativeFirebase { + import FirebaseModuleWithStaticsAndApp = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp; + interface Module { + appCheck: FirebaseModuleWithStaticsAndApp< + FirebaseAppCheckTypes.Module, + FirebaseAppCheckTypes.Statics + >; + } + interface FirebaseApp { + appCheck(): FirebaseAppCheckTypes.Module; + } + } +} diff --git a/packages/app-check/lib/index.js b/packages/app-check/lib/index.js new file mode 100644 index 0000000000..9342304d5a --- /dev/null +++ b/packages/app-check/lib/index.js @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { isIOS } from '@react-native-firebase/app/lib/common'; +import { + createModuleNamespace, + FirebaseModule, + getFirebaseRoot, +} from '@react-native-firebase/app/lib/internal'; + +import version from './version'; + +const statics = {}; + +const namespace = 'appCheck'; + +const nativeModuleName = 'RNFBAppCheckModule'; + +class FirebaseAppCheckModule extends FirebaseModule { + activate(siteKeyOrProvider, isTokenAutoRefreshEnabled) { + return this.native.activate(siteKeyOrProvider, isTokenAutoRefreshEnabled); + } + + setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled) { + this.native.setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled); + } + + getToken(forceRefresh) { + return this.native.getToken(forceRefresh); + } + + onTokenChanged() { + // iOS does not provide any native listening feature + if (isIOS) { + return; + } + // TODO unimplemented on Android + return; + } +} + +// import { SDK_VERSION } from '@react-native-firebase/app-check'; +export const SDK_VERSION = version; + +// import appCheck from '@react-native-firebase/app-check'; +// appCheck().X(...); +export default createModuleNamespace({ + statics, + version, + namespace, + nativeModuleName, + nativeEvents: false, // TODO verify if this is interesting - token refresh listener perhaps? + hasMultiAppSupport: true, + hasCustomUrlOrRegionSupport: false, + ModuleClass: FirebaseAppCheckModule, +}); + +// import appCheck, { firebase } from '@react-native-firebase/app-check'; +// appCheck().X(...); +// firebase.appCheck().X(...); +export const firebase = getFirebaseRoot(); diff --git a/packages/app-check/package.json b/packages/app-check/package.json new file mode 100644 index 0000000000..16f3eae4a7 --- /dev/null +++ b/packages/app-check/package.json @@ -0,0 +1,31 @@ +{ + "name": "@react-native-firebase/app-check", + "version": "12.4.0", + "author": "Invertase (http://invertase.io)", + "description": "React Native Firebase - App Check", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "scripts": { + "build": "genversion --semi lib/version.js", + "build:clean": "rimraf android/build && rimraf ios/build", + "prepare": "yarn run build" + }, + "repository": { + "type": "git", + "url": "https://github.com/invertase/react-native-firebase/tree/master/packages/app-check" + }, + "license": "Apache-2.0", + "keywords": [ + "react", + "react-native", + "firebase", + "app-check", + "appCheck" + ], + "peerDependencies": { + "@react-native-firebase/app": "12.4.0" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/app-check/type-test.ts b/packages/app-check/type-test.ts new file mode 100644 index 0000000000..03389aa715 --- /dev/null +++ b/packages/app-check/type-test.ts @@ -0,0 +1,26 @@ +import firebase from '@react-native-firebase/app'; +import defaultExport, { firebase as firebaseFromModule } from '@react-native-firebase/app-check'; + +// checks module exists at root +console.log(firebase.appCheck().app.name); + +// checks module exists at app level +console.log(firebase.app().appCheck().app.name); + +// checks statics exist +console.log(firebase.appCheck.SDK_VERSION); + +// checks statics exist on defaultExport +console.log(defaultExport.SDK_VERSION); + +// checks root exists +console.log(firebase.SDK_VERSION); + +// checks firebase named export exists on module +console.log(firebaseFromModule.SDK_VERSION); + +// checks multi-app support exists +console.log(firebase.appCheck(firebase.app()).app.name); + +// checks default export supports app arg +console.log(defaultExport(firebase.app()).app.name); diff --git a/packages/app/lib/internal/constants.js b/packages/app/lib/internal/constants.js index 880e46d2e5..4bc585ef6b 100644 --- a/packages/app/lib/internal/constants.js +++ b/packages/app/lib/internal/constants.js @@ -20,6 +20,7 @@ export const APP_NATIVE_MODULE = 'RNFBAppModule'; export const DEFAULT_APP_NAME = '[DEFAULT]'; export const KNOWN_NAMESPACES = [ + 'appCheck', 'auth', 'analytics', 'remoteConfig', diff --git a/packages/database/android/src/main/java/io/invertase/firebase/database/UniversalFirebaseDatabaseCommon.java b/packages/database/android/src/main/java/io/invertase/firebase/database/UniversalFirebaseDatabaseCommon.java index 7b6b9bbe86..4eea61ec0e 100644 --- a/packages/database/android/src/main/java/io/invertase/firebase/database/UniversalFirebaseDatabaseCommon.java +++ b/packages/database/android/src/main/java/io/invertase/firebase/database/UniversalFirebaseDatabaseCommon.java @@ -91,7 +91,6 @@ private static void setDatabaseConfig(FirebaseDatabase firebaseDatabase, String } static void addEmulatorConfig(String appName, String dbURL, String host, int port) { - System.err.println("adding emulator config"); String configKey = appName + dbURL; HashMap emulatorConfig = new HashMap<>(); emulatorConfig.put("host", host); diff --git a/scripts/_TEMPLATE_/README.md b/scripts/_TEMPLATE_/README.md index 2e469e31ef..4a0d333b5d 100644 --- a/scripts/_TEMPLATE_/README.md +++ b/scripts/_TEMPLATE_/README.md @@ -16,6 +16,7 @@

Chat on Discord Follow on Twitter + Follow on Facebook

---- @@ -30,7 +31,6 @@ Requires `@react-native-firebase/app` to be installed. ```bash yarn add @react-native-firebase/_template_ -react-native link @react-native-firebase/_template_ ``` ## Documentation @@ -50,11 +50,6 @@ react-native link @react-native-firebase/_template_

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':