@umituz/react-native-firebase 1.13.48 → 1.13.50
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/dist/scripts/cli-handlers.d.ts +27 -0
- package/dist/scripts/cli-handlers.d.ts.map +1 -0
- package/dist/scripts/cli-handlers.js +125 -0
- package/dist/scripts/cli-handlers.js.map +1 -0
- package/dist/scripts/cli-parser.d.ts +25 -0
- package/dist/scripts/cli-parser.d.ts.map +1 -0
- package/dist/scripts/cli-parser.js +101 -0
- package/dist/scripts/cli-parser.js.map +1 -0
- package/dist/scripts/cli.js +20 -155
- package/dist/scripts/cli.js.map +1 -1
- package/dist/scripts/firestore-operations.d.ts +18 -0
- package/dist/scripts/firestore-operations.d.ts.map +1 -0
- package/dist/scripts/firestore-operations.js +88 -0
- package/dist/scripts/firestore-operations.js.map +1 -0
- package/dist/scripts/firestore-queries.d.ts +27 -0
- package/dist/scripts/firestore-queries.d.ts.map +1 -0
- package/dist/scripts/firestore-queries.js +77 -0
- package/dist/scripts/firestore-queries.js.map +1 -0
- package/dist/scripts/firestore-seeding.d.ts +21 -0
- package/dist/scripts/firestore-seeding.d.ts.map +1 -0
- package/dist/scripts/firestore-seeding.js +67 -0
- package/dist/scripts/firestore-seeding.js.map +1 -0
- package/dist/scripts/firestore.d.ts +3 -48
- package/dist/scripts/firestore.d.ts.map +1 -1
- package/dist/scripts/firestore.js +16 -210
- package/dist/scripts/firestore.js.map +1 -1
- package/dist/scripts/user-commands.d.ts +33 -0
- package/dist/scripts/user-commands.d.ts.map +1 -0
- package/dist/scripts/user-commands.js +113 -0
- package/dist/scripts/user-commands.js.map +1 -0
- package/dist/scripts/user-formatters.d.ts +10 -0
- package/dist/scripts/user-formatters.d.ts.map +1 -0
- package/dist/scripts/user-formatters.js +55 -0
- package/dist/scripts/user-formatters.js.map +1 -0
- package/dist/scripts/user-queries.d.ts +42 -0
- package/dist/scripts/user-queries.d.ts.map +1 -0
- package/dist/scripts/user-queries.js +125 -0
- package/dist/scripts/user-queries.js.map +1 -0
- package/dist/scripts/user.d.ts +3 -67
- package/dist/scripts/user.d.ts.map +1 -1
- package/dist/scripts/user.js +15 -272
- package/dist/scripts/user.js.map +1 -1
- package/package.json +1 -1
- package/scripts/cli-handlers.ts +170 -0
- package/scripts/cli-parser.ts +82 -0
- package/scripts/cli.ts +27 -193
- package/scripts/firestore-operations.ts +111 -0
- package/scripts/firestore-queries.ts +97 -0
- package/scripts/firestore-seeding.ts +87 -0
- package/scripts/firestore.ts +20 -275
- package/scripts/user-commands.ts +104 -0
- package/scripts/user-formatters.ts +55 -0
- package/scripts/user-queries.ts +185 -0
- package/scripts/user.ts +19 -326
- package/src/auth/infrastructure/config/FirebaseAuthClient.ts +16 -171
- package/src/auth/infrastructure/services/account-deletion.service.ts +41 -351
- package/src/auth/infrastructure/services/reauthentication.service.ts +47 -207
- package/src/auth/infrastructure/services/reauthentication.types.ts +39 -0
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Reauthentication Service
|
|
3
3
|
* Handles Firebase Auth reauthentication for sensitive operations
|
|
4
|
-
*
|
|
5
|
-
* SOLID: Single Responsibility - Only handles reauthentication
|
|
6
4
|
*/
|
|
7
5
|
|
|
8
6
|
import {
|
|
@@ -11,243 +9,85 @@ import {
|
|
|
11
9
|
OAuthProvider,
|
|
12
10
|
EmailAuthProvider,
|
|
13
11
|
type User,
|
|
14
|
-
type AuthCredential,
|
|
15
12
|
} from "firebase/auth";
|
|
16
13
|
import * as AppleAuthentication from "expo-apple-authentication";
|
|
17
14
|
import * as Crypto from "expo-crypto";
|
|
18
15
|
import { Platform } from "react-native";
|
|
16
|
+
import type {
|
|
17
|
+
ReauthenticationResult,
|
|
18
|
+
AuthProviderType,
|
|
19
|
+
ReauthCredentialResult
|
|
20
|
+
} from "./reauthentication.types";
|
|
21
|
+
|
|
22
|
+
export type {
|
|
23
|
+
ReauthenticationResult,
|
|
24
|
+
AuthProviderType,
|
|
25
|
+
ReauthCredentialResult
|
|
26
|
+
} from "./reauthentication.types";
|
|
19
27
|
|
|
20
|
-
export interface ReauthenticationResult {
|
|
21
|
-
success: boolean;
|
|
22
|
-
error?: {
|
|
23
|
-
code: string;
|
|
24
|
-
message: string;
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export type AuthProviderType = "google.com" | "apple.com" | "password" | "anonymous" | "unknown";
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Get the primary auth provider for a user
|
|
32
|
-
*/
|
|
33
28
|
export function getUserAuthProvider(user: User): AuthProviderType {
|
|
34
|
-
if (user.isAnonymous)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (
|
|
40
|
-
return "unknown";
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Check for Google
|
|
44
|
-
const googleProvider = providerData.find((p) => p.providerId === "google.com");
|
|
45
|
-
if (googleProvider) {
|
|
46
|
-
return "google.com";
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Check for Apple
|
|
50
|
-
const appleProvider = providerData.find((p) => p.providerId === "apple.com");
|
|
51
|
-
if (appleProvider) {
|
|
52
|
-
return "apple.com";
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Check for password
|
|
56
|
-
const passwordProvider = providerData.find((p) => p.providerId === "password");
|
|
57
|
-
if (passwordProvider) {
|
|
58
|
-
return "password";
|
|
59
|
-
}
|
|
60
|
-
|
|
29
|
+
if (user.isAnonymous) return "anonymous";
|
|
30
|
+
const data = user.providerData;
|
|
31
|
+
if (!data?.length) return "unknown";
|
|
32
|
+
if (data.find(p => p.providerId === "google.com")) return "google.com";
|
|
33
|
+
if (data.find(p => p.providerId === "apple.com")) return "apple.com";
|
|
34
|
+
if (data.find(p => p.providerId === "password")) return "password";
|
|
61
35
|
return "unknown";
|
|
62
36
|
}
|
|
63
37
|
|
|
64
|
-
|
|
65
|
-
* Reauthenticate with Google
|
|
66
|
-
*/
|
|
67
|
-
export async function reauthenticateWithGoogle(
|
|
68
|
-
user: User,
|
|
69
|
-
idToken: string
|
|
70
|
-
): Promise<ReauthenticationResult> {
|
|
38
|
+
export async function reauthenticateWithGoogle(user: User, idToken: string): Promise<ReauthenticationResult> {
|
|
71
39
|
try {
|
|
72
|
-
|
|
73
|
-
await reauthenticateWithCredential(user, credential);
|
|
40
|
+
await reauthenticateWithCredential(user, GoogleAuthProvider.credential(idToken));
|
|
74
41
|
return { success: true };
|
|
75
|
-
} catch (error) {
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
success: false,
|
|
79
|
-
error: {
|
|
80
|
-
code: firebaseError.code || "auth/reauthentication-failed",
|
|
81
|
-
message: firebaseError.message || "Google reauthentication failed",
|
|
82
|
-
},
|
|
83
|
-
};
|
|
42
|
+
} catch (error: any) {
|
|
43
|
+
return { success: false, error: { code: error.code || "auth/failed", message: error.message } };
|
|
84
44
|
}
|
|
85
45
|
}
|
|
86
46
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
*/
|
|
90
|
-
export async function reauthenticateWithPassword(
|
|
91
|
-
user: User,
|
|
92
|
-
password: string
|
|
93
|
-
): Promise<ReauthenticationResult> {
|
|
47
|
+
export async function reauthenticateWithPassword(user: User, pass: string): Promise<ReauthenticationResult> {
|
|
48
|
+
if (!user.email) return { success: false, error: { code: "auth/no-email", message: "User has no email" } };
|
|
94
49
|
try {
|
|
95
|
-
|
|
96
|
-
return {
|
|
97
|
-
success: false,
|
|
98
|
-
error: {
|
|
99
|
-
code: "auth/no-email",
|
|
100
|
-
message: "User has no email address",
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const credential = EmailAuthProvider.credential(user.email, password);
|
|
106
|
-
await reauthenticateWithCredential(user, credential);
|
|
50
|
+
await reauthenticateWithCredential(user, EmailAuthProvider.credential(user.email, pass));
|
|
107
51
|
return { success: true };
|
|
108
|
-
} catch (error) {
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
success: false,
|
|
112
|
-
error: {
|
|
113
|
-
code: firebaseError.code || "auth/reauthentication-failed",
|
|
114
|
-
message: firebaseError.message || "Password reauthentication failed",
|
|
115
|
-
},
|
|
116
|
-
};
|
|
52
|
+
} catch (error: any) {
|
|
53
|
+
return { success: false, error: { code: error.code || "auth/failed", message: error.message } };
|
|
117
54
|
}
|
|
118
55
|
}
|
|
119
56
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
*/
|
|
123
|
-
async function generateNonce(length: number = 32): Promise<string> {
|
|
124
|
-
const randomBytes = await Crypto.getRandomBytesAsync(length);
|
|
57
|
+
async function generateNonce(len: number = 32): Promise<string> {
|
|
58
|
+
const bytes = await Crypto.getRandomBytesAsync(len);
|
|
125
59
|
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
for (let i = 0; i < randomBytes.length; i++) {
|
|
129
|
-
const byte = randomBytes[i];
|
|
130
|
-
if (byte !== undefined) {
|
|
131
|
-
result += chars.charAt(byte % chars.length);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return result;
|
|
60
|
+
return Array.from(bytes).map(b => chars.charAt(b % chars.length)).join("");
|
|
136
61
|
}
|
|
137
62
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
* Returns the credential that can be used for reauthentication
|
|
141
|
-
*/
|
|
142
|
-
export async function getAppleReauthCredential(): Promise<{
|
|
143
|
-
success: boolean;
|
|
144
|
-
credential?: AuthCredential;
|
|
145
|
-
error?: { code: string; message: string };
|
|
146
|
-
}> {
|
|
147
|
-
if (Platform.OS !== "ios") {
|
|
148
|
-
return {
|
|
149
|
-
success: false,
|
|
150
|
-
error: {
|
|
151
|
-
code: "auth/platform-not-supported",
|
|
152
|
-
message: "Apple Sign-In is only available on iOS",
|
|
153
|
-
},
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
|
|
63
|
+
export async function getAppleReauthCredential(): Promise<ReauthCredentialResult> {
|
|
64
|
+
if (Platform.OS !== "ios") return { success: false, error: { code: "auth/ios-only", message: "iOS only" } };
|
|
157
65
|
try {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
return {
|
|
161
|
-
success: false,
|
|
162
|
-
error: {
|
|
163
|
-
code: "auth/apple-signin-unavailable",
|
|
164
|
-
message: "Apple Sign-In is not available on this device",
|
|
165
|
-
},
|
|
166
|
-
};
|
|
167
|
-
}
|
|
66
|
+
if (!(await AppleAuthentication.isAvailableAsync()))
|
|
67
|
+
return { success: false, error: { code: "auth/unavailable", message: "Unavailable" } };
|
|
168
68
|
|
|
169
|
-
// Generate nonce
|
|
170
69
|
const nonce = await generateNonce();
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
// Request Apple Sign-In
|
|
177
|
-
const appleCredential = await AppleAuthentication.signInAsync({
|
|
178
|
-
requestedScopes: [
|
|
179
|
-
AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
|
|
180
|
-
AppleAuthentication.AppleAuthenticationScope.EMAIL,
|
|
181
|
-
],
|
|
182
|
-
nonce: hashedNonce,
|
|
70
|
+
const hashed = await Crypto.digestStringAsync(Crypto.CryptoDigestAlgorithm.SHA256, nonce);
|
|
71
|
+
const apple = await AppleAuthentication.signInAsync({
|
|
72
|
+
requestedScopes: [AppleAuthentication.AppleAuthenticationScope.FULL_NAME, AppleAuthentication.AppleAuthenticationScope.EMAIL],
|
|
73
|
+
nonce: hashed,
|
|
183
74
|
});
|
|
184
75
|
|
|
185
|
-
if (!
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
message: "No identity token received from Apple",
|
|
191
|
-
},
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Create Firebase credential
|
|
196
|
-
const provider = new OAuthProvider("apple.com");
|
|
197
|
-
const credential = provider.credential({
|
|
198
|
-
idToken: appleCredential.identityToken,
|
|
199
|
-
rawNonce: nonce,
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
return { success: true, credential };
|
|
203
|
-
} catch (error) {
|
|
204
|
-
if (error instanceof Error && error.message.includes("ERR_CANCELED")) {
|
|
205
|
-
return {
|
|
206
|
-
success: false,
|
|
207
|
-
error: {
|
|
208
|
-
code: "auth/cancelled",
|
|
209
|
-
message: "Apple Sign-In was cancelled",
|
|
210
|
-
},
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return {
|
|
215
|
-
success: false,
|
|
216
|
-
error: {
|
|
217
|
-
code: "auth/apple-reauthentication-failed",
|
|
218
|
-
message: error instanceof Error ? error.message : "Apple reauthentication failed",
|
|
219
|
-
},
|
|
220
|
-
};
|
|
76
|
+
if (!apple.identityToken) return { success: false, error: { code: "auth/no-token", message: "No token" } };
|
|
77
|
+
return { success: true, credential: new OAuthProvider("apple.com").credential({ idToken: apple.identityToken, rawNonce: nonce }) };
|
|
78
|
+
} catch (error: any) {
|
|
79
|
+
const code = error.message?.includes("ERR_CANCELED") ? "auth/cancelled" : "auth/failed";
|
|
80
|
+
return { success: false, error: { code, message: error.message } };
|
|
221
81
|
}
|
|
222
82
|
}
|
|
223
83
|
|
|
224
|
-
/**
|
|
225
|
-
* Reauthenticate with Apple
|
|
226
|
-
*/
|
|
227
84
|
export async function reauthenticateWithApple(user: User): Promise<ReauthenticationResult> {
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
if (!result.success || !result.credential) {
|
|
231
|
-
return {
|
|
232
|
-
success: false,
|
|
233
|
-
error: result.error || {
|
|
234
|
-
code: "auth/no-credential",
|
|
235
|
-
message: "Failed to get Apple credential",
|
|
236
|
-
},
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
|
|
85
|
+
const res = await getAppleReauthCredential();
|
|
86
|
+
if (!res.success || !res.credential) return { success: false, error: res.error };
|
|
240
87
|
try {
|
|
241
|
-
await reauthenticateWithCredential(user,
|
|
88
|
+
await reauthenticateWithCredential(user, res.credential);
|
|
242
89
|
return { success: true };
|
|
243
|
-
} catch (error) {
|
|
244
|
-
|
|
245
|
-
return {
|
|
246
|
-
success: false,
|
|
247
|
-
error: {
|
|
248
|
-
code: firebaseError.code || "auth/reauthentication-failed",
|
|
249
|
-
message: firebaseError.message || "Apple reauthentication failed",
|
|
250
|
-
},
|
|
251
|
-
};
|
|
90
|
+
} catch (error: any) {
|
|
91
|
+
return { success: false, error: { code: error.code || "auth/failed", message: error.message } };
|
|
252
92
|
}
|
|
253
93
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reauthentication Types
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { AuthCredential } from "firebase/auth";
|
|
6
|
+
|
|
7
|
+
export interface ReauthenticationResult {
|
|
8
|
+
success: boolean;
|
|
9
|
+
error?: {
|
|
10
|
+
code: string;
|
|
11
|
+
message: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type AuthProviderType = "google.com" | "apple.com" | "password" | "anonymous" | "unknown";
|
|
16
|
+
|
|
17
|
+
export interface ReauthCredentialResult {
|
|
18
|
+
success: boolean;
|
|
19
|
+
credential?: AuthCredential;
|
|
20
|
+
error?: { code: string; message: string };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface AccountDeletionResult {
|
|
24
|
+
success: boolean;
|
|
25
|
+
error?: {
|
|
26
|
+
code: string;
|
|
27
|
+
message: string;
|
|
28
|
+
requiresReauth: boolean;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface AccountDeletionOptions {
|
|
33
|
+
/** Google ID token for reauthentication */
|
|
34
|
+
googleIdToken?: string;
|
|
35
|
+
/** Password for reauthentication */
|
|
36
|
+
password?: string;
|
|
37
|
+
/** Attempt Apple reauth automatically */
|
|
38
|
+
autoReauthenticate?: boolean;
|
|
39
|
+
}
|