@umituz/react-native-firebase 2.6.2 → 2.6.4

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.
Files changed (101) hide show
  1. package/package.json +1 -1
  2. package/src/application/auth/index.ts +2 -34
  3. package/src/application/auth/use-cases/index.ts +1 -21
  4. package/src/domains/account-deletion/domain/index.ts +1 -8
  5. package/src/domains/account-deletion/index.ts +0 -42
  6. package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor.ts +79 -0
  7. package/src/domains/account-deletion/infrastructure/services/AccountDeletionTypes.ts +0 -1
  8. package/src/domains/account-deletion/infrastructure/services/account-deletion.service.ts +2 -14
  9. package/src/domains/auth/index.ts +3 -12
  10. package/src/domains/auth/infrastructure.ts +11 -0
  11. package/src/domains/firestore/domain/entities/Collection.ts +0 -2
  12. package/src/domains/firestore/domain/index.ts +8 -12
  13. package/src/domains/firestore/domain/value-objects/{QueryOptions.ts.bak → QueryOptions.ts} +20 -68
  14. package/src/domains/firestore/domain/value-objects/QueryOptionsFactory.ts +95 -0
  15. package/src/domains/firestore/domain/value-objects/QueryOptionsHelpers.ts +110 -0
  16. package/src/domains/firestore/domain/value-objects/WhereClause.ts +115 -0
  17. package/src/domains/firestore/domain/value-objects/WhereClauseFactory.ts +101 -0
  18. package/src/domains/firestore/domain/value-objects/WhereClauseHelpers.ts +123 -0
  19. package/src/domains/firestore/domain/value-objects/WhereClauseValidation.ts +83 -0
  20. package/src/domains/firestore/presentation/hooks/useFirestoreMutation.ts +1 -1
  21. package/src/domains/firestore/presentation/hooks/useFirestoreQuery.ts +1 -1
  22. package/src/shared/infrastructure/config/base/ServiceClientSingleton.ts +29 -0
  23. package/src/application/auth/ports/AuthPort.ts.bak +0 -164
  24. package/src/application/auth/ports/AuthPort_part_aa +0 -150
  25. package/src/application/auth/ports/AuthPort_part_ab +0 -14
  26. package/src/application/auth/use-cases/SignInUseCase.ts.bak +0 -253
  27. package/src/application/auth/use-cases/SignInUseCaseHelpers.ts +0 -0
  28. package/src/application/auth/use-cases/SignInUseCaseMain.ts +0 -0
  29. package/src/application/auth/use-cases/SignInUseCase_part_aa +0 -150
  30. package/src/application/auth/use-cases/SignInUseCase_part_ab +0 -103
  31. package/src/application/auth/use-cases/SignOutUseCase.ts.bak +0 -288
  32. package/src/application/auth/use-cases/SignOutUseCaseCleanup.ts +0 -0
  33. package/src/application/auth/use-cases/SignOutUseCaseMain.ts +0 -0
  34. package/src/application/auth/use-cases/SignOutUseCase_part_aa +0 -150
  35. package/src/application/auth/use-cases/SignOutUseCase_part_ab +0 -138
  36. package/src/domains/account-deletion/domain/services/UserValidationHelpers.ts.bak +0 -181
  37. package/src/domains/account-deletion/domain/services/UserValidationHelpers_part_aa +0 -150
  38. package/src/domains/account-deletion/domain/services/UserValidationHelpers_part_ab +0 -31
  39. package/src/domains/account-deletion/domain/services/UserValidationService.ts.bak +0 -286
  40. package/src/domains/account-deletion/domain/services/UserValidationService_part_aa +0 -150
  41. package/src/domains/account-deletion/domain/services/UserValidationService_part_ab +0 -136
  42. package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor.ts.bak +0 -230
  43. package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor_part_aa +0 -150
  44. package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor_part_ab +0 -80
  45. package/src/domains/account-deletion/infrastructure/services/AccountDeletionReauthHandler.ts.bak +0 -174
  46. package/src/domains/account-deletion/infrastructure/services/AccountDeletionReauthHandler_part_aa +0 -150
  47. package/src/domains/account-deletion/infrastructure/services/AccountDeletionReauthHandler_part_ab +0 -24
  48. package/src/domains/account-deletion/infrastructure/services/AccountDeletionRepository.ts.bak +0 -266
  49. package/src/domains/account-deletion/infrastructure/services/AccountDeletionRepository_part_aa +0 -150
  50. package/src/domains/account-deletion/infrastructure/services/AccountDeletionRepository_part_ab +0 -116
  51. package/src/domains/account-deletion/infrastructure/services/reauthentication.service.ts.bak +0 -160
  52. package/src/domains/account-deletion/infrastructure/services/reauthentication.service_part_aa +0 -150
  53. package/src/domains/account-deletion/infrastructure/services/reauthentication.service_part_ab +0 -10
  54. package/src/domains/auth/infrastructure.ts.bak +0 -156
  55. package/src/domains/auth/infrastructure_part_aa +0 -150
  56. package/src/domains/auth/infrastructure_part_ab +0 -6
  57. package/src/domains/auth/presentation/hooks/GoogleOAuthHelpers.ts +0 -0
  58. package/src/domains/auth/presentation/hooks/GoogleOAuthHookService.ts.bak +0 -247
  59. package/src/domains/auth/presentation/hooks/GoogleOAuthHookService_part_aa +0 -150
  60. package/src/domains/auth/presentation/hooks/GoogleOAuthHookService_part_ab +0 -97
  61. package/src/domains/auth/presentation/hooks/GoogleOAuthService.ts +0 -0
  62. package/src/domains/firestore/domain/entities/Collection.ts.bak +0 -288
  63. package/src/domains/firestore/domain/entities/Collection_part_aa +0 -150
  64. package/src/domains/firestore/domain/entities/Collection_part_ab +0 -138
  65. package/src/domains/firestore/domain/entities/Document.ts.bak +0 -233
  66. package/src/domains/firestore/domain/entities/DocumentHelpers.ts +0 -0
  67. package/src/domains/firestore/domain/entities/DocumentMain.ts +0 -0
  68. package/src/domains/firestore/domain/entities/Document_part_aa +0 -150
  69. package/src/domains/firestore/domain/entities/Document_part_ab +0 -83
  70. package/src/domains/firestore/domain/services/QueryService.ts.bak +0 -182
  71. package/src/domains/firestore/domain/services/QueryServiceAnalysis.ts.bak +0 -169
  72. package/src/domains/firestore/domain/services/QueryServiceAnalysis_part_aa +0 -150
  73. package/src/domains/firestore/domain/services/QueryServiceAnalysis_part_ab +0 -19
  74. package/src/domains/firestore/domain/services/QueryServiceHelpers.ts.bak +0 -151
  75. package/src/domains/firestore/domain/services/QueryServiceHelpers_part_aa +0 -150
  76. package/src/domains/firestore/domain/services/QueryServiceHelpers_part_ab +0 -1
  77. package/src/domains/firestore/domain/services/QueryService_part_aa +0 -150
  78. package/src/domains/firestore/domain/services/QueryService_part_ab +0 -32
  79. package/src/domains/firestore/domain/value-objects/QueryOptionsSerialization.ts.bak +0 -207
  80. package/src/domains/firestore/domain/value-objects/QueryOptionsSerialization_part_aa +0 -150
  81. package/src/domains/firestore/domain/value-objects/QueryOptionsSerialization_part_ab +0 -57
  82. package/src/domains/firestore/domain/value-objects/QueryOptionsValidation.ts.bak +0 -182
  83. package/src/domains/firestore/domain/value-objects/QueryOptionsValidation_part_aa +0 -150
  84. package/src/domains/firestore/domain/value-objects/QueryOptionsValidation_part_ab +0 -32
  85. package/src/domains/firestore/domain/value-objects/QueryOptions_part_aa +0 -150
  86. package/src/domains/firestore/domain/value-objects/QueryOptions_part_ab +0 -41
  87. package/src/domains/firestore/domain/value-objects/WhereClause.ts.bak +0 -299
  88. package/src/domains/firestore/domain/value-objects/WhereClauseFactory.ts.bak +0 -207
  89. package/src/domains/firestore/domain/value-objects/WhereClauseFactory_part_aa +0 -150
  90. package/src/domains/firestore/domain/value-objects/WhereClauseFactory_part_ab +0 -57
  91. package/src/domains/firestore/domain/value-objects/WhereClause_part_aa +0 -150
  92. package/src/domains/firestore/domain/value-objects/WhereClause_part_ab +0 -149
  93. package/src/shared/infrastructure/base/ErrorHandler.ts.bak +0 -189
  94. package/src/shared/infrastructure/base/ErrorHandler_part_aa +0 -150
  95. package/src/shared/infrastructure/base/ErrorHandler_part_ab +0 -39
  96. package/src/shared/infrastructure/base/ServiceBase.ts.bak +0 -220
  97. package/src/shared/infrastructure/base/ServiceBase_part_aa +0 -150
  98. package/src/shared/infrastructure/base/ServiceBase_part_ab +0 -70
  99. package/src/shared/infrastructure/config/base/ServiceClientSingleton.ts.bak +0 -155
  100. package/src/shared/infrastructure/config/base/ServiceClientSingleton_part_aa +0 -150
  101. package/src/shared/infrastructure/config/base/ServiceClientSingleton_part_ab +0 -5
@@ -1,286 +0,0 @@
1
- /**
2
- * User Validation Service (Main)
3
- * Single Responsibility: Validate user state for account operations
4
- *
5
- * Domain service that encapsulates user validation logic.
6
- * Moves business logic from infrastructure to domain layer.
7
- *
8
- * Max lines: 150 (enforced for maintainability)
9
- */
10
-
11
- import type { Auth, User } from 'firebase/auth';
12
- import type { Result } from '../../../../shared/domain/utils';
13
- import { successResult, failureResultFrom } from '../../../../shared/domain/utils';
14
-
15
- /**
16
- * User validation service
17
- * Provides user validation functionality for account operations
18
- */
19
- export class UserValidationService {
20
- /**
21
- * Validate user is ready for deletion
22
- * Checks user exists, not anonymous, and has required provider
23
- */
24
- validateForDeletion(user: User | null): Result<{ userId: string; provider: string }> {
25
- if (!user) {
26
- return failureResultFrom('auth/not-ready', 'No authenticated user');
27
- }
28
-
29
- if (user.isAnonymous) {
30
- return failureResultFrom('auth/anonymous', 'Cannot delete anonymous account');
31
- }
32
-
33
- const provider = this.getUserAuthProvider(user);
34
- if (!provider) {
35
- return failureResultFrom('auth/unsupported', 'Unsupported auth provider');
36
- }
37
-
38
- return successResult({
39
- userId: user.uid,
40
- provider,
41
- });
42
- }
43
-
44
- /**
45
- * Validate user hasn't changed during operation
46
- * Critical for preventing race conditions
47
- */
48
- validateUserUnchanged(auth: Auth | null, originalUserId: string): Result<void> {
49
- if (!auth) {
50
- return failureResultFrom('auth/not-ready', 'Auth not initialized');
51
- }
52
-
53
- const currentUserId = auth.currentUser?.uid;
54
-
55
- if (!currentUserId) {
56
- return failureResultFrom('auth/user-signed-out', 'User signed out during operation');
57
- }
58
-
59
- if (currentUserId !== originalUserId) {
60
- return failureResultFrom('auth/user-changed', 'User changed during operation');
61
- }
62
-
63
- return successResult();
64
- }
65
-
66
- /**
67
- * Validate user credentials are present
68
- */
69
- validateCredentials(
70
- user: User,
71
- options: {
72
- password?: string;
73
- googleIdToken?: string;
74
- }
75
- ): Result<void> {
76
- const provider = this.getUserAuthProvider(user);
77
-
78
- if (provider === 'password' && !options.password) {
79
- return failureResultFrom('auth/password-required', 'Password required for reauthentication');
80
- }
81
-
82
- if (provider === 'google.com' && !options.googleIdToken) {
83
- return failureResultFrom('auth/google-token-required', 'Google ID token required for reauthentication');
84
- }
85
-
86
- return successResult();
87
- }
88
-
89
- /**
90
- * Get user's auth provider
91
- * Returns provider ID or null if unknown
92
- */
93
- getUserAuthProvider(user: User): string | null {
94
- if (!user.providerData || user.providerData.length === 0) {
95
- return null;
96
- }
97
-
98
- // Check all providers
99
- for (const userInfo of user.providerData) {
100
- if (userInfo.providerId) {
101
- return userInfo.providerId;
102
- }
103
- }
104
-
105
- return null;
106
- }
107
-
108
- /**
109
- * Check if user has specific provider
110
- */
111
- hasProvider(user: User, providerId: string): boolean {
112
- if (!user.providerData || user.providerData.length === 0) {
113
- return false;
114
- }
115
-
116
- return user.providerData.some(
117
- userInfo => userInfo.providerId === providerId
118
- );
119
- }
120
-
121
- /**
122
- * Check if user is email/password user
123
- */
124
- isEmailPasswordUser(user: User): boolean {
125
- return this.hasProvider(user, 'password');
126
- }
127
-
128
- /**
129
- * Check if user is Google user
130
- */
131
- isGoogleUser(user: User): boolean {
132
- return this.hasProvider(user, 'google.com');
133
- }
134
-
135
- /**
136
- * Check if user is Apple user
137
- */
138
- isAppleUser(user: User): boolean {
139
- return this.hasProvider(user, 'apple.com');
140
- }
141
-
142
- /**
143
- * Check if user requires reauthentication
144
- * Based on provider and operation type
145
- */
146
- requiresReauthentication(user: User, operation: 'delete' | 'update'): boolean {
147
- // Email/password users always need recent auth
148
- if (this.isEmailPasswordUser(user)) {
149
- return true;
150
- }
151
-
152
- // Social providers may require recent auth for sensitive operations
153
- if (operation === 'delete') {
154
- return true;
155
- }
156
-
157
- return false;
158
- }
159
-
160
- /**
161
- * Validate user email
162
- */
163
- validateEmail(user: User): Result<void> {
164
- const email = user.email;
165
-
166
- if (!email) {
167
- return failureResultFrom('auth/no-email', 'User has no email');
168
- }
169
-
170
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
171
- if (!emailRegex.test(email)) {
172
- return failureResultFrom('auth/invalid-email', 'Invalid email format');
173
- }
174
-
175
- return successResult();
176
- }
177
-
178
- /**
179
- * Validate user is verified (if applicable)
180
- */
181
- validateVerified(user: User, requireVerification: boolean = false): Result<void> {
182
- if (requireVerification && !user.emailVerified) {
183
- return failureResultFrom('auth/unverified', 'Email not verified');
184
- }
185
-
186
- return successResult();
187
- }
188
-
189
- /**
190
- * Get user metadata
191
- */
192
- getUserMetadata(user: User): {
193
- readonly createdAt: number | null;
194
- readonly lastSignInAt: number | null;
195
- } {
196
- return {
197
- createdAt: user.metadata.creationTime ? new Date(user.metadata.creationTime).getTime() : null,
198
- lastSignInAt: user.metadata.lastSignInTime ? new Date(user.metadata.lastSignInTime).getTime() : null,
199
- };
200
- }
201
-
202
- /**
203
- * Check if account is new (created recently)
204
- */
205
- isAccountNew(user: User, maxAgeMs: number = 24 * 60 * 60 * 1000): boolean {
206
- const metadata = this.getUserMetadata(user);
207
- if (!metadata.createdAt) return false;
208
-
209
- const age = Date.now() - metadata.createdAt;
210
- return age <= maxAgeMs;
211
- }
212
-
213
- /**
214
- * Check if user recently signed in
215
- */
216
- isRecentSignIn(user: User, maxAgeMs: number = 5 * 60 * 1000): boolean {
217
- const metadata = this.getUserMetadata(user);
218
- if (!metadata.lastSignInAt) return false;
219
-
220
- const timeSinceSignIn = Date.now() - metadata.lastSignInAt;
221
- return timeSinceSignIn <= maxAgeMs;
222
- }
223
-
224
- /**
225
- * Validate user can perform operation
226
- * Comprehensive check combining multiple validations
227
- */
228
- validateCanPerformOperation(
229
- user: User | null,
230
- operation: 'delete' | 'update',
231
- options: {
232
- requireVerified?: boolean;
233
- maxSignInAge?: number;
234
- password?: string;
235
- googleIdToken?: string;
236
- } = {}
237
- ): Result<{ userId: string; provider: string }> {
238
- // Validate user ready for operation
239
- const deletionValidation = this.validateForDeletion(user);
240
- if (!deletionValidation.success) {
241
- return deletionValidation;
242
- }
243
-
244
- const userId = deletionValidation.data!.userId;
245
- const provider = deletionValidation.data!.provider;
246
-
247
- // Validate email
248
- if (user) {
249
- const emailValidation = this.validateEmail(user);
250
- if (!emailValidation.success) {
251
- return emailValidation;
252
- }
253
-
254
- // Validate verification status
255
- const verifiedValidation = this.validateVerified(user, options.requireVerified);
256
- if (!verifiedValidation.success) {
257
- return verifiedValidation;
258
- }
259
-
260
- // Check if recent sign-in required
261
- if (options.maxSignInAge && !this.isRecentSignIn(user, options.maxSignInAge)) {
262
- return failureResultFrom('auth/stale-session', 'Session too old, please sign in again');
263
- }
264
-
265
- // Validate credentials
266
- const credentialsValidation = this.validateCredentials(user, options);
267
- if (!credentialsValidation.success) {
268
- return credentialsValidation;
269
- }
270
- }
271
-
272
- return successResult({ userId, provider });
273
- }
274
- }
275
-
276
- /**
277
- * Factory function to create user validation service
278
- */
279
- export function createUserValidationService(): UserValidationService {
280
- return new UserValidationService();
281
- }
282
-
283
- /**
284
- * Default instance for convenience
285
- */
286
- export const userValidationService = createUserValidationService();
@@ -1,150 +0,0 @@
1
- /**
2
- * User Validation Service (Main)
3
- * Single Responsibility: Validate user state for account operations
4
- *
5
- * Domain service that encapsulates user validation logic.
6
- * Moves business logic from infrastructure to domain layer.
7
- *
8
- * Max lines: 150 (enforced for maintainability)
9
- */
10
-
11
- import type { Auth, User } from 'firebase/auth';
12
- import type { Result } from '../../../../shared/domain/utils';
13
- import { successResult, failureResultFrom } from '../../../../shared/domain/utils';
14
-
15
- /**
16
- * User validation service
17
- * Provides user validation functionality for account operations
18
- */
19
- export class UserValidationService {
20
- /**
21
- * Validate user is ready for deletion
22
- * Checks user exists, not anonymous, and has required provider
23
- */
24
- validateForDeletion(user: User | null): Result<{ userId: string; provider: string }> {
25
- if (!user) {
26
- return failureResultFrom('auth/not-ready', 'No authenticated user');
27
- }
28
-
29
- if (user.isAnonymous) {
30
- return failureResultFrom('auth/anonymous', 'Cannot delete anonymous account');
31
- }
32
-
33
- const provider = this.getUserAuthProvider(user);
34
- if (!provider) {
35
- return failureResultFrom('auth/unsupported', 'Unsupported auth provider');
36
- }
37
-
38
- return successResult({
39
- userId: user.uid,
40
- provider,
41
- });
42
- }
43
-
44
- /**
45
- * Validate user hasn't changed during operation
46
- * Critical for preventing race conditions
47
- */
48
- validateUserUnchanged(auth: Auth | null, originalUserId: string): Result<void> {
49
- if (!auth) {
50
- return failureResultFrom('auth/not-ready', 'Auth not initialized');
51
- }
52
-
53
- const currentUserId = auth.currentUser?.uid;
54
-
55
- if (!currentUserId) {
56
- return failureResultFrom('auth/user-signed-out', 'User signed out during operation');
57
- }
58
-
59
- if (currentUserId !== originalUserId) {
60
- return failureResultFrom('auth/user-changed', 'User changed during operation');
61
- }
62
-
63
- return successResult();
64
- }
65
-
66
- /**
67
- * Validate user credentials are present
68
- */
69
- validateCredentials(
70
- user: User,
71
- options: {
72
- password?: string;
73
- googleIdToken?: string;
74
- }
75
- ): Result<void> {
76
- const provider = this.getUserAuthProvider(user);
77
-
78
- if (provider === 'password' && !options.password) {
79
- return failureResultFrom('auth/password-required', 'Password required for reauthentication');
80
- }
81
-
82
- if (provider === 'google.com' && !options.googleIdToken) {
83
- return failureResultFrom('auth/google-token-required', 'Google ID token required for reauthentication');
84
- }
85
-
86
- return successResult();
87
- }
88
-
89
- /**
90
- * Get user's auth provider
91
- * Returns provider ID or null if unknown
92
- */
93
- getUserAuthProvider(user: User): string | null {
94
- if (!user.providerData || user.providerData.length === 0) {
95
- return null;
96
- }
97
-
98
- // Check all providers
99
- for (const userInfo of user.providerData) {
100
- if (userInfo.providerId) {
101
- return userInfo.providerId;
102
- }
103
- }
104
-
105
- return null;
106
- }
107
-
108
- /**
109
- * Check if user has specific provider
110
- */
111
- hasProvider(user: User, providerId: string): boolean {
112
- if (!user.providerData || user.providerData.length === 0) {
113
- return false;
114
- }
115
-
116
- return user.providerData.some(
117
- userInfo => userInfo.providerId === providerId
118
- );
119
- }
120
-
121
- /**
122
- * Check if user is email/password user
123
- */
124
- isEmailPasswordUser(user: User): boolean {
125
- return this.hasProvider(user, 'password');
126
- }
127
-
128
- /**
129
- * Check if user is Google user
130
- */
131
- isGoogleUser(user: User): boolean {
132
- return this.hasProvider(user, 'google.com');
133
- }
134
-
135
- /**
136
- * Check if user is Apple user
137
- */
138
- isAppleUser(user: User): boolean {
139
- return this.hasProvider(user, 'apple.com');
140
- }
141
-
142
- /**
143
- * Check if user requires reauthentication
144
- * Based on provider and operation type
145
- */
146
- requiresReauthentication(user: User, operation: 'delete' | 'update'): boolean {
147
- // Email/password users always need recent auth
148
- if (this.isEmailPasswordUser(user)) {
149
- return true;
150
- }
@@ -1,136 +0,0 @@
1
-
2
- // Social providers may require recent auth for sensitive operations
3
- if (operation === 'delete') {
4
- return true;
5
- }
6
-
7
- return false;
8
- }
9
-
10
- /**
11
- * Validate user email
12
- */
13
- validateEmail(user: User): Result<void> {
14
- const email = user.email;
15
-
16
- if (!email) {
17
- return failureResultFrom('auth/no-email', 'User has no email');
18
- }
19
-
20
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
21
- if (!emailRegex.test(email)) {
22
- return failureResultFrom('auth/invalid-email', 'Invalid email format');
23
- }
24
-
25
- return successResult();
26
- }
27
-
28
- /**
29
- * Validate user is verified (if applicable)
30
- */
31
- validateVerified(user: User, requireVerification: boolean = false): Result<void> {
32
- if (requireVerification && !user.emailVerified) {
33
- return failureResultFrom('auth/unverified', 'Email not verified');
34
- }
35
-
36
- return successResult();
37
- }
38
-
39
- /**
40
- * Get user metadata
41
- */
42
- getUserMetadata(user: User): {
43
- readonly createdAt: number | null;
44
- readonly lastSignInAt: number | null;
45
- } {
46
- return {
47
- createdAt: user.metadata.creationTime ? new Date(user.metadata.creationTime).getTime() : null,
48
- lastSignInAt: user.metadata.lastSignInTime ? new Date(user.metadata.lastSignInTime).getTime() : null,
49
- };
50
- }
51
-
52
- /**
53
- * Check if account is new (created recently)
54
- */
55
- isAccountNew(user: User, maxAgeMs: number = 24 * 60 * 60 * 1000): boolean {
56
- const metadata = this.getUserMetadata(user);
57
- if (!metadata.createdAt) return false;
58
-
59
- const age = Date.now() - metadata.createdAt;
60
- return age <= maxAgeMs;
61
- }
62
-
63
- /**
64
- * Check if user recently signed in
65
- */
66
- isRecentSignIn(user: User, maxAgeMs: number = 5 * 60 * 1000): boolean {
67
- const metadata = this.getUserMetadata(user);
68
- if (!metadata.lastSignInAt) return false;
69
-
70
- const timeSinceSignIn = Date.now() - metadata.lastSignInAt;
71
- return timeSinceSignIn <= maxAgeMs;
72
- }
73
-
74
- /**
75
- * Validate user can perform operation
76
- * Comprehensive check combining multiple validations
77
- */
78
- validateCanPerformOperation(
79
- user: User | null,
80
- operation: 'delete' | 'update',
81
- options: {
82
- requireVerified?: boolean;
83
- maxSignInAge?: number;
84
- password?: string;
85
- googleIdToken?: string;
86
- } = {}
87
- ): Result<{ userId: string; provider: string }> {
88
- // Validate user ready for operation
89
- const deletionValidation = this.validateForDeletion(user);
90
- if (!deletionValidation.success) {
91
- return deletionValidation;
92
- }
93
-
94
- const userId = deletionValidation.data!.userId;
95
- const provider = deletionValidation.data!.provider;
96
-
97
- // Validate email
98
- if (user) {
99
- const emailValidation = this.validateEmail(user);
100
- if (!emailValidation.success) {
101
- return emailValidation;
102
- }
103
-
104
- // Validate verification status
105
- const verifiedValidation = this.validateVerified(user, options.requireVerified);
106
- if (!verifiedValidation.success) {
107
- return verifiedValidation;
108
- }
109
-
110
- // Check if recent sign-in required
111
- if (options.maxSignInAge && !this.isRecentSignIn(user, options.maxSignInAge)) {
112
- return failureResultFrom('auth/stale-session', 'Session too old, please sign in again');
113
- }
114
-
115
- // Validate credentials
116
- const credentialsValidation = this.validateCredentials(user, options);
117
- if (!credentialsValidation.success) {
118
- return credentialsValidation;
119
- }
120
- }
121
-
122
- return successResult({ userId, provider });
123
- }
124
- }
125
-
126
- /**
127
- * Factory function to create user validation service
128
- */
129
- export function createUserValidationService(): UserValidationService {
130
- return new UserValidationService();
131
- }
132
-
133
- /**
134
- * Default instance for convenience
135
- */
136
- export const userValidationService = createUserValidationService();