@chem-po/firebase-native 0.0.38 → 0.0.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/adapter/auth.js +10 -3
- package/lib/commonjs/adapter/auth.js.map +1 -1
- package/lib/commonjs/components/FirebaseSignIn.js +20 -14
- package/lib/commonjs/components/FirebaseSignIn.js.map +1 -1
- package/lib/commonjs/components/PhoneVerify.js +45 -33
- package/lib/commonjs/components/PhoneVerify.js.map +1 -1
- package/lib/commonjs/components/TwoFactorAuthModal.js +72 -15
- package/lib/commonjs/components/TwoFactorAuthModal.js.map +1 -1
- package/lib/commonjs/hooks/usePhoneVerify.js +13 -5
- package/lib/commonjs/hooks/usePhoneVerify.js.map +1 -1
- package/lib/commonjs/utils/validation.js +4 -0
- package/lib/commonjs/utils/validation.js.map +1 -1
- package/lib/module/adapter/auth.js +10 -3
- package/lib/module/adapter/auth.js.map +1 -1
- package/lib/module/components/FirebaseSignIn.js +21 -15
- package/lib/module/components/FirebaseSignIn.js.map +1 -1
- package/lib/module/components/PhoneVerify.js +47 -35
- package/lib/module/components/PhoneVerify.js.map +1 -1
- package/lib/module/components/TwoFactorAuthModal.js +71 -15
- package/lib/module/components/TwoFactorAuthModal.js.map +1 -1
- package/lib/module/hooks/usePhoneVerify.js +13 -5
- package/lib/module/hooks/usePhoneVerify.js.map +1 -1
- package/lib/module/utils/validation.js +4 -0
- package/lib/module/utils/validation.js.map +1 -1
- package/lib/typescript/adapter/auth.d.ts.map +1 -1
- package/lib/typescript/components/FirebaseSignIn.d.ts.map +1 -1
- package/lib/typescript/components/PhoneVerify.d.ts.map +1 -1
- package/lib/typescript/components/TwoFactorAuthModal.d.ts +1 -0
- package/lib/typescript/components/TwoFactorAuthModal.d.ts.map +1 -1
- package/lib/typescript/hooks/usePhoneVerify.d.ts +3 -1
- package/lib/typescript/hooks/usePhoneVerify.d.ts.map +1 -1
- package/lib/typescript/utils/validation.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/adapter/auth.ts +98 -83
- package/src/components/FirebaseSignIn.tsx +21 -14
- package/src/components/PhoneVerify.tsx +46 -33
- package/src/components/TwoFactorAuthModal.tsx +87 -23
- package/src/hooks/usePhoneVerify.ts +15 -4
- package/src/utils/validation.ts +7 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { EnrollmentFactor, PhoneEnrollmentFactor } from '@chem-po/core'
|
|
2
|
-
import { useAuth, useBackgroundColor } from '@chem-po/react'
|
|
2
|
+
import { useAuth, useBackgroundColor, useBorderColor, useIconColor } from '@chem-po/react'
|
|
3
3
|
import { Txt } from '@chem-po/react-native'
|
|
4
|
+
import { useFont } from '@chem-po/react-native/src/hooks/useFont'
|
|
5
|
+
import { Ionicons } from '@expo/vector-icons'
|
|
4
6
|
import React, { useState } from 'react'
|
|
5
7
|
import { ScrollView, StyleSheet, TouchableOpacity, View } from 'react-native'
|
|
6
8
|
import { Modal, Portal } from 'react-native-paper'
|
|
@@ -8,6 +10,46 @@ import { useBackend } from '../hooks/backend'
|
|
|
8
10
|
import { AuthenticatorVerify } from './AuthenticatorVerify'
|
|
9
11
|
import { PhoneVerify } from './PhoneVerify'
|
|
10
12
|
|
|
13
|
+
const FactorView = ({
|
|
14
|
+
factor,
|
|
15
|
+
buttonBackgroundColor,
|
|
16
|
+
iconColor,
|
|
17
|
+
borderColor,
|
|
18
|
+
onPress,
|
|
19
|
+
}: {
|
|
20
|
+
factor: EnrollmentFactor
|
|
21
|
+
buttonBackgroundColor: string
|
|
22
|
+
iconColor: string
|
|
23
|
+
borderColor: string
|
|
24
|
+
onPress: () => void
|
|
25
|
+
}) => {
|
|
26
|
+
return (
|
|
27
|
+
<TouchableOpacity
|
|
28
|
+
style={[
|
|
29
|
+
styles.factorButton,
|
|
30
|
+
{
|
|
31
|
+
backgroundColor: buttonBackgroundColor,
|
|
32
|
+
borderColor,
|
|
33
|
+
},
|
|
34
|
+
]}
|
|
35
|
+
onPress={onPress}
|
|
36
|
+
>
|
|
37
|
+
<View style={styles.factorContent}>
|
|
38
|
+
<Ionicons
|
|
39
|
+
name={factor.type === 'phone' ? 'phone-portrait' : 'qr-code'}
|
|
40
|
+
size={20}
|
|
41
|
+
color={iconColor}
|
|
42
|
+
/>
|
|
43
|
+
<Txt style={styles.factorHeaderText}>
|
|
44
|
+
{factor.type === 'phone' ? `Phone: ${factor.phoneNumber}` : 'Authenticator App'}
|
|
45
|
+
</Txt>
|
|
46
|
+
{factor.displayName ? (
|
|
47
|
+
<Txt style={styles.factorDetailsText}>{factor.displayName}</Txt>
|
|
48
|
+
) : null}
|
|
49
|
+
</View>
|
|
50
|
+
</TouchableOpacity>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
11
53
|
|
|
12
54
|
const TwoFactorSelect = ({
|
|
13
55
|
factors,
|
|
@@ -17,30 +59,22 @@ const TwoFactorSelect = ({
|
|
|
17
59
|
onSelect: (factor: EnrollmentFactor) => void
|
|
18
60
|
}) => {
|
|
19
61
|
const buttonBackgroundColor = useBackgroundColor(100)
|
|
62
|
+
const borderColor = useBorderColor()
|
|
63
|
+
const iconColor = useIconColor()
|
|
64
|
+
const textFont = useFont('body', 'md')
|
|
20
65
|
return (
|
|
21
66
|
<View style={styles.selectContainer}>
|
|
22
|
-
<Txt style={styles.selectTitle}>Select an option to verify with:</Txt>
|
|
67
|
+
<Txt style={[styles.selectTitle, textFont]}>Select an option to verify with:</Txt>
|
|
23
68
|
<View style={styles.factorsList}>
|
|
24
69
|
{factors.map((factor) => (
|
|
25
|
-
<
|
|
26
|
-
key={factor.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
{
|
|
30
|
-
backgroundColor: buttonBackgroundColor,
|
|
31
|
-
},
|
|
32
|
-
]}
|
|
70
|
+
<FactorView
|
|
71
|
+
key={`${factor.type}-${factor.enrollmentTime}`}
|
|
72
|
+
factor={factor}
|
|
73
|
+
buttonBackgroundColor={buttonBackgroundColor}
|
|
33
74
|
onPress={() => onSelect(factor)}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
</Txt>
|
|
38
|
-
{
|
|
39
|
-
factor.displayName ? (
|
|
40
|
-
<Txt style={styles.factorDetailsText}>{factor.displayName}</Txt>
|
|
41
|
-
) : null
|
|
42
|
-
}
|
|
43
|
-
</TouchableOpacity>
|
|
75
|
+
iconColor={iconColor}
|
|
76
|
+
borderColor={borderColor}
|
|
77
|
+
/>
|
|
44
78
|
))}
|
|
45
79
|
</View>
|
|
46
80
|
</View>
|
|
@@ -83,7 +117,9 @@ export const TwoFactorAuthModal = () => {
|
|
|
83
117
|
<Portal>
|
|
84
118
|
<Modal
|
|
85
119
|
visible={true}
|
|
86
|
-
onDismiss={() => {
|
|
120
|
+
onDismiss={() => {
|
|
121
|
+
auth.logout()
|
|
122
|
+
}}
|
|
87
123
|
style={styles.modal}
|
|
88
124
|
>
|
|
89
125
|
<View style={[styles.modalContent, { backgroundColor }]}>
|
|
@@ -96,6 +132,28 @@ export const TwoFactorAuthModal = () => {
|
|
|
96
132
|
)
|
|
97
133
|
}
|
|
98
134
|
|
|
135
|
+
const testFactor: EnrollmentFactor = {
|
|
136
|
+
uid: 'test',
|
|
137
|
+
type: 'phone',
|
|
138
|
+
phoneNumber: '1234567890',
|
|
139
|
+
displayName: 'Test Phone',
|
|
140
|
+
enrollmentTime: '2021-01-01',
|
|
141
|
+
}
|
|
142
|
+
export const TestTwoFactorVerifyModal = () => {
|
|
143
|
+
const backgroundColor = useBackgroundColor(150)
|
|
144
|
+
return (
|
|
145
|
+
<Portal>
|
|
146
|
+
<Modal visible={true} onDismiss={() => {}} style={styles.modal}>
|
|
147
|
+
<View style={[styles.modalContent, { backgroundColor }]}>
|
|
148
|
+
<ScrollView contentContainerStyle={styles.scrollContent}>
|
|
149
|
+
<TwoFactorVerify factorInfo={testFactor} />
|
|
150
|
+
</ScrollView>
|
|
151
|
+
</View>
|
|
152
|
+
</Modal>
|
|
153
|
+
</Portal>
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
|
|
99
157
|
const styles = StyleSheet.create({
|
|
100
158
|
modal: {
|
|
101
159
|
margin: 0,
|
|
@@ -113,18 +171,24 @@ const styles = StyleSheet.create({
|
|
|
113
171
|
},
|
|
114
172
|
selectTitle: {
|
|
115
173
|
fontSize: 16,
|
|
116
|
-
marginBottom:
|
|
174
|
+
marginBottom: 8,
|
|
175
|
+
paddingHorizontal: 4,
|
|
117
176
|
},
|
|
118
177
|
factorsList: {
|
|
119
178
|
gap: 8,
|
|
120
179
|
},
|
|
180
|
+
factorContent: {
|
|
181
|
+
flexDirection: 'row',
|
|
182
|
+
alignItems: 'center',
|
|
183
|
+
gap: 8,
|
|
184
|
+
},
|
|
121
185
|
factorButton: {
|
|
122
186
|
padding: 16,
|
|
123
187
|
borderRadius: 8,
|
|
124
188
|
borderWidth: 1,
|
|
125
189
|
},
|
|
126
190
|
factorHeaderText: {
|
|
127
|
-
fontSize:
|
|
191
|
+
fontSize: 16,
|
|
128
192
|
fontWeight: 'bold',
|
|
129
193
|
opacity: 0.8,
|
|
130
194
|
},
|
|
@@ -5,6 +5,7 @@ import { useBackend } from './backend'
|
|
|
5
5
|
|
|
6
6
|
export const usePhoneVerify = (factor: PhoneEnrollmentFactor, automaticallySendSmsCode: boolean) => {
|
|
7
7
|
const [code, setCode] = useState('')
|
|
8
|
+
const [sendingCode, setSendingCode] = useState(false)
|
|
8
9
|
const [verifying, setVerifying] = useState(false)
|
|
9
10
|
const [error, setError] = useState('')
|
|
10
11
|
|
|
@@ -15,14 +16,22 @@ export const usePhoneVerify = (factor: PhoneEnrollmentFactor, automaticallySendS
|
|
|
15
16
|
|
|
16
17
|
const initSendCode = useRef(!!automaticallySendSmsCode)
|
|
17
18
|
|
|
18
|
-
const { showSuccess, showError
|
|
19
|
+
const { showSuccess, showError } = useToast()
|
|
19
20
|
|
|
20
21
|
const sendCode = useCallback(async () => {
|
|
21
22
|
if (!enrollmentFactors) {
|
|
22
23
|
showError('Error - No session found')
|
|
23
24
|
return
|
|
24
25
|
}
|
|
25
|
-
|
|
26
|
+
setSendingCode(true)
|
|
27
|
+
return auth.sendMultiFactorCode(factor, enrollmentFactors.multiFactorResolver)
|
|
28
|
+
.then(() => {
|
|
29
|
+
setSendingCode(false)
|
|
30
|
+
})
|
|
31
|
+
.catch((e) => {
|
|
32
|
+
setSendingCode(false)
|
|
33
|
+
setError(e.message || 'An error occurred')
|
|
34
|
+
})
|
|
26
35
|
}, [auth, factor, twoFactorVerification, showError])
|
|
27
36
|
|
|
28
37
|
const initSendCodeFunc = useRef(sendCode)
|
|
@@ -32,7 +41,7 @@ export const usePhoneVerify = (factor: PhoneEnrollmentFactor, automaticallySendS
|
|
|
32
41
|
}
|
|
33
42
|
}, [])
|
|
34
43
|
|
|
35
|
-
const handleVerify = useCallback(() => {
|
|
44
|
+
const handleVerify = useCallback(async () => {
|
|
36
45
|
setVerifying(true)
|
|
37
46
|
setError('')
|
|
38
47
|
if (!twoFactorVerification) {
|
|
@@ -54,7 +63,7 @@ export const usePhoneVerify = (factor: PhoneEnrollmentFactor, automaticallySendS
|
|
|
54
63
|
showError('Error - Two factor verification is not supported')
|
|
55
64
|
return
|
|
56
65
|
}
|
|
57
|
-
verify(twoFactorVerification, code)
|
|
66
|
+
return verify(twoFactorVerification, code)
|
|
58
67
|
.then(() => {
|
|
59
68
|
setVerifying(false)
|
|
60
69
|
setCode('')
|
|
@@ -69,7 +78,9 @@ export const usePhoneVerify = (factor: PhoneEnrollmentFactor, automaticallySendS
|
|
|
69
78
|
return {
|
|
70
79
|
code,
|
|
71
80
|
setCode,
|
|
81
|
+
sendCode,
|
|
72
82
|
verifying,
|
|
83
|
+
sendingCode,
|
|
73
84
|
error,
|
|
74
85
|
handleVerify,
|
|
75
86
|
}
|
package/src/utils/validation.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BaseAuthProvider, GoogleAuthProvider } from '@chem-po/core'
|
|
2
|
+
import { Platform } from 'react-native'
|
|
2
3
|
|
|
3
4
|
interface ValidationResult {
|
|
4
5
|
isValid: boolean
|
|
@@ -27,6 +28,12 @@ export const validateAuthConfiguration = (providers: BaseAuthProvider[]): Valida
|
|
|
27
28
|
'Google webClientId format looks incorrect. Expected format: "xxx.apps.googleusercontent.com"',
|
|
28
29
|
)
|
|
29
30
|
}
|
|
31
|
+
if (Platform.OS === 'ios' && !googleProvider.iosClientId) {
|
|
32
|
+
errors.push(
|
|
33
|
+
'Google provider is missing iosClientId. ' +
|
|
34
|
+
'Get this from Firebase Console > Authentication > Sign-in method > Google > iOS SDK configuration',
|
|
35
|
+
)
|
|
36
|
+
}
|
|
30
37
|
}
|
|
31
38
|
|
|
32
39
|
// Check environment
|