@react-native-firebase/auth 21.6.1 → 21.6.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.multiline_appDelegateOpenUrlInsertionPointAfter = exports.appDelegateOpenUrlInsertionPointAfter = exports.withIosCaptchaOpenUrlFix = void 0;
4
+ exports.shouldApplyIosOpenUrlFix = shouldApplyIosOpenUrlFix;
5
+ exports.withOpenUrlFixForAppDelegate = withOpenUrlFixForAppDelegate;
6
+ exports.modifyObjcAppDelegate = modifyObjcAppDelegate;
7
+ exports.isFirebaseSwizzlingDisabled = isFirebaseSwizzlingDisabled;
8
+ exports.ensureFirebaseSwizzlingIsEnabled = ensureFirebaseSwizzlingIsEnabled;
9
+ const config_plugins_1 = require("@expo/config-plugins");
10
+ const generateCode_1 = require("@expo/config-plugins/build/utils/generateCode");
11
+ const withIosCaptchaOpenUrlFix = (config, props) => {
12
+ // check configuration
13
+ if (!shouldApplyIosOpenUrlFix({ config, props })) {
14
+ return config;
15
+ }
16
+ // check that swizzling is enabled; otherwise patch must be customized and applied manually
17
+ (0, config_plugins_1.withInfoPlist)(config, config => {
18
+ ensureFirebaseSwizzlingIsEnabled(config);
19
+ return config;
20
+ });
21
+ // apply patch
22
+ return (0, config_plugins_1.withAppDelegate)(config, config => {
23
+ return withOpenUrlFixForAppDelegate({ config, props });
24
+ });
25
+ };
26
+ exports.withIosCaptchaOpenUrlFix = withIosCaptchaOpenUrlFix;
27
+ // Interpret the plugin config to determine whether this fix should be applied
28
+ function shouldApplyIosOpenUrlFix({ config, props, }) {
29
+ const flag = props?.ios?.captchaOpenUrlFix;
30
+ if (flag === undefined || flag === 'default') {
31
+ // by default, apply the fix whenever 'expo-router' is detected in the same project
32
+ return isPluginEnabled(config, 'expo-router');
33
+ }
34
+ else if (flag === true || flag === false) {
35
+ const isEnabled = flag;
36
+ return isEnabled;
37
+ }
38
+ else {
39
+ throw new Error(`Unexpected value for 'captchaOpenUrlFix' config option`);
40
+ }
41
+ }
42
+ function withOpenUrlFixForAppDelegate({ config, props, }) {
43
+ const { language, contents } = config.modResults;
44
+ const configValue = props?.ios?.captchaOpenUrlFix || 'default';
45
+ if (['objc', 'objcpp'].includes(language)) {
46
+ const newContents = modifyObjcAppDelegate(contents);
47
+ if (newContents === null) {
48
+ if (configValue === true) {
49
+ throw new Error("Failed to apply iOS openURL fix because no 'openURL' method was found");
50
+ }
51
+ else {
52
+ config_plugins_1.WarningAggregator.addWarningIOS('@react-native-firebase/auth', "Skipping iOS openURL fix because no 'openURL' method was found");
53
+ return config;
54
+ }
55
+ }
56
+ else {
57
+ if (configValue === 'default') {
58
+ config_plugins_1.WarningAggregator.addWarningIOS('@react-native-firebase/auth', 'modifying iOS AppDelegate openURL method to ignore firebaseauth reCAPTCHA redirect URLs');
59
+ }
60
+ return {
61
+ ...config,
62
+ modResults: {
63
+ ...config.modResults,
64
+ contents: newContents,
65
+ },
66
+ };
67
+ }
68
+ }
69
+ else {
70
+ // TODO: Support Swift
71
+ throw new Error(`Don't know how to apply openUrlFix to AppDelegate of language "${language}"`);
72
+ }
73
+ }
74
+ const skipOpenUrlForFirebaseAuthBlock = `\
75
+ if ([url.host caseInsensitiveCompare:@"firebaseauth"] == NSOrderedSame) {
76
+ // invocations for Firebase Auth are handled elsewhere and should not be forwarded to Expo Router
77
+ return NO;
78
+ }\
79
+ `;
80
+ // NOTE: `mergeContents()` requires that this pattern not match newlines
81
+ exports.appDelegateOpenUrlInsertionPointAfter = /-\s*\(\s*BOOL\s*\)\s*application\s*:\s*\(\s*UIApplication\s*\*\s*\)\s*application\s+openURL\s*:\s*\(\s*NSURL\s*\*\s*\)\s*url\s+options\s*:\s*\(\s*NSDictionary\s*<\s*UIApplicationOpenURLOptionsKey\s*,\s*id\s*>\s*\*\s*\)\s*options\s*/; // 🙈
82
+ exports.multiline_appDelegateOpenUrlInsertionPointAfter = new RegExp(exports.appDelegateOpenUrlInsertionPointAfter.source + '\\s*{\\s*\\n');
83
+ // Returns contents of new AppDelegate with modification applied, or returns null if this patch is not applicable because the AppDelegate doesn't have an 'openURL' method to handle deep links.
84
+ function modifyObjcAppDelegate(contents) {
85
+ const pattern = exports.appDelegateOpenUrlInsertionPointAfter;
86
+ const multilinePattern = exports.multiline_appDelegateOpenUrlInsertionPointAfter;
87
+ const fullMatch = contents.match(multilinePattern);
88
+ if (!fullMatch) {
89
+ if (contents.match(pattern)) {
90
+ throw new Error("Failed to find insertion point; expected newline after '{'");
91
+ }
92
+ else if (contents.match(/openURL\s*:/)) {
93
+ throw new Error([
94
+ "Failed to apply 'captchaOpenUrlFix' but detected 'openURL' method.",
95
+ "Please manually apply the fix to your AppDelegate's openURL method,",
96
+ "then update your app.config.json by configuring the '@react-native-firebase/auth' plugin",
97
+ 'to set `captchaOpenUrlFix: false`.',
98
+ ].join(' '));
99
+ }
100
+ else {
101
+ // openURL method was not found in AppDelegate
102
+ return null;
103
+ }
104
+ }
105
+ const fullMatchNumLines = fullMatch[0].split('\n').length;
106
+ const offset = fullMatchNumLines - 1;
107
+ if (offset < 0) {
108
+ throw new Error(`Failed to find insertion point; fullMatchNumLines=${fullMatchNumLines}`);
109
+ }
110
+ return (0, generateCode_1.mergeContents)({
111
+ tag: '@react-native-firebase/auth-openURL',
112
+ src: contents,
113
+ newSrc: skipOpenUrlForFirebaseAuthBlock,
114
+ anchor: exports.appDelegateOpenUrlInsertionPointAfter,
115
+ offset,
116
+ comment: '//',
117
+ }).contents;
118
+ }
119
+ // Search the ExpoConfig plugins array to see if `pluginName` is present
120
+ function isPluginEnabled(config, pluginName) {
121
+ if (config.plugins === undefined) {
122
+ return false;
123
+ }
124
+ return config.plugins.some((plugin) => {
125
+ if (plugin === pluginName) {
126
+ return true;
127
+ }
128
+ else if (Array.isArray(plugin) && plugin.length >= 1 && plugin[0] === pluginName) {
129
+ return true;
130
+ }
131
+ else {
132
+ return false;
133
+ }
134
+ });
135
+ }
136
+ function isFirebaseSwizzlingDisabled(config) {
137
+ return config.ios?.infoPlist?.['FirebaseAppDelegateProxyEnabled'] === false;
138
+ }
139
+ function ensureFirebaseSwizzlingIsEnabled(config) {
140
+ if (isFirebaseSwizzlingDisabled(config)) {
141
+ throw new Error([
142
+ 'Your app has disabled swizzling by setting FirebaseAppDelegateProxyEnabled=false in its Info.plist.',
143
+ "Please update your app.config.json to configure the '@react-native-firebase/auth' plugin to set `captchaOpenUrlFix: false`",
144
+ 'and see https://firebase.google.com/docs/auth/ios/phone-auth#appendix:-using-phone-sign-in-without-swizzling for instructions.',
145
+ ].join(' '));
146
+ }
147
+ else {
148
+ return true;
149
+ }
150
+ }
@@ -1,5 +1,6 @@
1
1
  import { ConfigPlugin, IOSConfig, ExportedConfigWithProps } from '@expo/config-plugins';
2
- export declare const withIosCaptchaUrlTypes: ConfigPlugin;
2
+ import { PluginConfigType } from '../pluginConfig';
3
+ export declare const withIosCaptchaUrlTypes: ConfigPlugin<PluginConfigType>;
3
4
  export declare function setUrlTypesForCaptcha({ config, }: {
4
5
  config: ExportedConfigWithProps<IOSConfig.InfoPlist>;
5
6
  }): ExportedConfigWithProps<IOSConfig.InfoPlist>;
@@ -0,0 +1,6 @@
1
+ export interface PluginConfigType {
2
+ ios?: PluginConfigTypeIos;
3
+ }
4
+ export interface PluginConfigTypeIos {
5
+ captchaOpenUrlFix?: undefined | boolean | 'default';
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,14 +1,16 @@
1
1
  import { ConfigPlugin, withPlugins, createRunOncePlugin } from '@expo/config-plugins';
2
2
 
3
- import { withIosCaptchaUrlTypes } from './ios';
3
+ import { withIosCaptchaUrlTypes, withIosCaptchaOpenUrlFix } from './ios';
4
+ import { PluginConfigType } from './pluginConfig';
4
5
 
5
6
  /**
6
7
  * A config plugin for configuring `@react-native-firebase/auth`
7
8
  */
8
- const withRnFirebaseAuth: ConfigPlugin = config => {
9
+ const withRnFirebaseAuth: ConfigPlugin<PluginConfigType> = (config, props) => {
9
10
  return withPlugins(config, [
10
11
  // iOS
11
- withIosCaptchaUrlTypes,
12
+ [withIosCaptchaUrlTypes, props],
13
+ [withIosCaptchaOpenUrlFix, props],
12
14
  ]);
13
15
  };
14
16
 
@@ -1,3 +1,4 @@
1
1
  import { withIosCaptchaUrlTypes } from './urlTypes';
2
+ import { withIosCaptchaOpenUrlFix } from './openUrlFix';
2
3
 
3
- export { withIosCaptchaUrlTypes };
4
+ export { withIosCaptchaUrlTypes, withIosCaptchaOpenUrlFix };
@@ -0,0 +1,186 @@
1
+ import {
2
+ ConfigPlugin,
3
+ withAppDelegate,
4
+ withInfoPlist,
5
+ ExportedConfigWithProps,
6
+ WarningAggregator,
7
+ } from '@expo/config-plugins';
8
+ import type { ExpoConfig } from '@expo/config/build/Config.types';
9
+ import type { AppDelegateProjectFile } from '@expo/config-plugins/build/ios/Paths';
10
+ import type { InfoPlist } from '@expo/config-plugins/build/ios/IosConfig.types';
11
+ import { mergeContents } from '@expo/config-plugins/build/utils/generateCode';
12
+ import { PluginConfigType } from '../pluginConfig';
13
+
14
+ export const withIosCaptchaOpenUrlFix: ConfigPlugin<PluginConfigType> = (
15
+ config: ExpoConfig,
16
+ props?: PluginConfigType,
17
+ ) => {
18
+ // check configuration
19
+ if (!shouldApplyIosOpenUrlFix({ config, props })) {
20
+ return config;
21
+ }
22
+
23
+ // check that swizzling is enabled; otherwise patch must be customized and applied manually
24
+ withInfoPlist(config, config => {
25
+ ensureFirebaseSwizzlingIsEnabled(config);
26
+ return config;
27
+ });
28
+
29
+ // apply patch
30
+ return withAppDelegate(config, config => {
31
+ return withOpenUrlFixForAppDelegate({ config, props });
32
+ });
33
+ };
34
+
35
+ // Interpret the plugin config to determine whether this fix should be applied
36
+ export function shouldApplyIosOpenUrlFix({
37
+ config,
38
+ props,
39
+ }: {
40
+ config: ExpoConfig;
41
+ props?: PluginConfigType;
42
+ }): boolean {
43
+ const flag = props?.ios?.captchaOpenUrlFix;
44
+ if (flag === undefined || flag === 'default') {
45
+ // by default, apply the fix whenever 'expo-router' is detected in the same project
46
+ return isPluginEnabled(config, 'expo-router');
47
+ } else if (flag === true || flag === false) {
48
+ const isEnabled: boolean = flag;
49
+ return isEnabled;
50
+ } else {
51
+ throw new Error(`Unexpected value for 'captchaOpenUrlFix' config option`);
52
+ }
53
+ }
54
+
55
+ export function withOpenUrlFixForAppDelegate({
56
+ config,
57
+ props,
58
+ }: {
59
+ config: ExportedConfigWithProps<AppDelegateProjectFile>;
60
+ props?: PluginConfigType;
61
+ }) {
62
+ const { language, contents } = config.modResults;
63
+ const configValue = props?.ios?.captchaOpenUrlFix || 'default';
64
+
65
+ if (['objc', 'objcpp'].includes(language)) {
66
+ const newContents = modifyObjcAppDelegate(contents);
67
+ if (newContents === null) {
68
+ if (configValue === true) {
69
+ throw new Error("Failed to apply iOS openURL fix because no 'openURL' method was found");
70
+ } else {
71
+ WarningAggregator.addWarningIOS(
72
+ '@react-native-firebase/auth',
73
+ "Skipping iOS openURL fix because no 'openURL' method was found",
74
+ );
75
+ return config;
76
+ }
77
+ } else {
78
+ if (configValue === 'default') {
79
+ WarningAggregator.addWarningIOS(
80
+ '@react-native-firebase/auth',
81
+ 'modifying iOS AppDelegate openURL method to ignore firebaseauth reCAPTCHA redirect URLs',
82
+ );
83
+ }
84
+ return {
85
+ ...config,
86
+ modResults: {
87
+ ...config.modResults,
88
+ contents: newContents,
89
+ },
90
+ };
91
+ }
92
+ } else {
93
+ // TODO: Support Swift
94
+ throw new Error(`Don't know how to apply openUrlFix to AppDelegate of language "${language}"`);
95
+ }
96
+ }
97
+
98
+ const skipOpenUrlForFirebaseAuthBlock: string = `\
99
+ if ([url.host caseInsensitiveCompare:@"firebaseauth"] == NSOrderedSame) {
100
+ // invocations for Firebase Auth are handled elsewhere and should not be forwarded to Expo Router
101
+ return NO;
102
+ }\
103
+ `;
104
+
105
+ // NOTE: `mergeContents()` requires that this pattern not match newlines
106
+ export const appDelegateOpenUrlInsertionPointAfter: RegExp =
107
+ /-\s*\(\s*BOOL\s*\)\s*application\s*:\s*\(\s*UIApplication\s*\*\s*\)\s*application\s+openURL\s*:\s*\(\s*NSURL\s*\*\s*\)\s*url\s+options\s*:\s*\(\s*NSDictionary\s*<\s*UIApplicationOpenURLOptionsKey\s*,\s*id\s*>\s*\*\s*\)\s*options\s*/; // 🙈
108
+
109
+ export const multiline_appDelegateOpenUrlInsertionPointAfter = new RegExp(
110
+ appDelegateOpenUrlInsertionPointAfter.source + '\\s*{\\s*\\n',
111
+ );
112
+
113
+ // Returns contents of new AppDelegate with modification applied, or returns null if this patch is not applicable because the AppDelegate doesn't have an 'openURL' method to handle deep links.
114
+ export function modifyObjcAppDelegate(contents: string): string | null {
115
+ const pattern = appDelegateOpenUrlInsertionPointAfter;
116
+ const multilinePattern = multiline_appDelegateOpenUrlInsertionPointAfter;
117
+ const fullMatch = contents.match(multilinePattern);
118
+ if (!fullMatch) {
119
+ if (contents.match(pattern)) {
120
+ throw new Error("Failed to find insertion point; expected newline after '{'");
121
+ } else if (contents.match(/openURL\s*:/)) {
122
+ throw new Error(
123
+ [
124
+ "Failed to apply 'captchaOpenUrlFix' but detected 'openURL' method.",
125
+ "Please manually apply the fix to your AppDelegate's openURL method,",
126
+ "then update your app.config.json by configuring the '@react-native-firebase/auth' plugin",
127
+ 'to set `captchaOpenUrlFix: false`.',
128
+ ].join(' '),
129
+ );
130
+ } else {
131
+ // openURL method was not found in AppDelegate
132
+ return null;
133
+ }
134
+ }
135
+ const fullMatchNumLines = fullMatch[0].split('\n').length;
136
+ const offset = fullMatchNumLines - 1;
137
+ if (offset < 0) {
138
+ throw new Error(`Failed to find insertion point; fullMatchNumLines=${fullMatchNumLines}`);
139
+ }
140
+ return mergeContents({
141
+ tag: '@react-native-firebase/auth-openURL',
142
+ src: contents,
143
+ newSrc: skipOpenUrlForFirebaseAuthBlock,
144
+ anchor: appDelegateOpenUrlInsertionPointAfter,
145
+ offset,
146
+ comment: '//',
147
+ }).contents;
148
+ }
149
+
150
+ export type ExpoConfigPluginEntry = string | [] | [string] | [string, any];
151
+
152
+ // Search the ExpoConfig plugins array to see if `pluginName` is present
153
+ function isPluginEnabled(config: ExpoConfig, pluginName: string): boolean {
154
+ if (config.plugins === undefined) {
155
+ return false;
156
+ }
157
+ return config.plugins.some((plugin: ExpoConfigPluginEntry) => {
158
+ if (plugin === pluginName) {
159
+ return true;
160
+ } else if (Array.isArray(plugin) && plugin.length >= 1 && plugin[0] === pluginName) {
161
+ return true;
162
+ } else {
163
+ return false;
164
+ }
165
+ });
166
+ }
167
+
168
+ export function isFirebaseSwizzlingDisabled(config: ExportedConfigWithProps<InfoPlist>): boolean {
169
+ return config.ios?.infoPlist?.['FirebaseAppDelegateProxyEnabled'] === false;
170
+ }
171
+
172
+ export function ensureFirebaseSwizzlingIsEnabled(
173
+ config: ExportedConfigWithProps<InfoPlist>,
174
+ ): boolean {
175
+ if (isFirebaseSwizzlingDisabled(config)) {
176
+ throw new Error(
177
+ [
178
+ 'Your app has disabled swizzling by setting FirebaseAppDelegateProxyEnabled=false in its Info.plist.',
179
+ "Please update your app.config.json to configure the '@react-native-firebase/auth' plugin to set `captchaOpenUrlFix: false`",
180
+ 'and see https://firebase.google.com/docs/auth/ios/phone-auth#appendix:-using-phone-sign-in-without-swizzling for instructions.',
181
+ ].join(' '),
182
+ );
183
+ } else {
184
+ return true;
185
+ }
186
+ }
@@ -7,9 +7,10 @@ import {
7
7
  import fs from 'fs';
8
8
  import path from 'path';
9
9
  import plist from 'plist';
10
+ import { PluginConfigType } from '../pluginConfig';
10
11
 
11
12
  // does this for you: https://firebase.google.com/docs/auth/ios/phone-auth#enable-phone-number-sign-in-for-your-firebase-project
12
- export const withIosCaptchaUrlTypes: ConfigPlugin = config => {
13
+ export const withIosCaptchaUrlTypes: ConfigPlugin<PluginConfigType> = config => {
13
14
  return withInfoPlist(config, config => {
14
15
  return setUrlTypesForCaptcha({ config });
15
16
  });
@@ -0,0 +1,7 @@
1
+ export interface PluginConfigType {
2
+ ios?: PluginConfigTypeIos;
3
+ }
4
+
5
+ export interface PluginConfigTypeIos {
6
+ captchaOpenUrlFix?: undefined | boolean | 'default';
7
+ }
@@ -1 +1 @@
1
- {"root":["./src/index.ts","./src/ios/index.ts","./src/ios/urlTypes.ts"],"version":"5.6.2"}
1
+ {"root":["./src/index.ts","./src/pluginConfig.ts","./src/ios/index.ts","./src/ios/openUrlFix.ts","./src/ios/urlTypes.ts"],"version":"5.6.2"}