@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.
- package/package.json +1 -1
- package/src/application/auth/index.ts +2 -34
- package/src/application/auth/use-cases/index.ts +1 -21
- package/src/domains/account-deletion/domain/index.ts +1 -8
- package/src/domains/account-deletion/index.ts +0 -42
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor.ts +79 -0
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionTypes.ts +0 -1
- package/src/domains/account-deletion/infrastructure/services/account-deletion.service.ts +2 -14
- package/src/domains/auth/index.ts +3 -12
- package/src/domains/auth/infrastructure.ts +11 -0
- package/src/domains/firestore/domain/entities/Collection.ts +0 -2
- package/src/domains/firestore/domain/index.ts +8 -12
- package/src/domains/firestore/domain/value-objects/{QueryOptions.ts.bak → QueryOptions.ts} +20 -68
- package/src/domains/firestore/domain/value-objects/QueryOptionsFactory.ts +95 -0
- package/src/domains/firestore/domain/value-objects/QueryOptionsHelpers.ts +110 -0
- package/src/domains/firestore/domain/value-objects/WhereClause.ts +115 -0
- package/src/domains/firestore/domain/value-objects/WhereClauseFactory.ts +101 -0
- package/src/domains/firestore/domain/value-objects/WhereClauseHelpers.ts +123 -0
- package/src/domains/firestore/domain/value-objects/WhereClauseValidation.ts +83 -0
- package/src/domains/firestore/presentation/hooks/useFirestoreMutation.ts +1 -1
- package/src/domains/firestore/presentation/hooks/useFirestoreQuery.ts +1 -1
- package/src/shared/infrastructure/config/base/ServiceClientSingleton.ts +29 -0
- package/src/application/auth/ports/AuthPort.ts.bak +0 -164
- package/src/application/auth/ports/AuthPort_part_aa +0 -150
- package/src/application/auth/ports/AuthPort_part_ab +0 -14
- package/src/application/auth/use-cases/SignInUseCase.ts.bak +0 -253
- package/src/application/auth/use-cases/SignInUseCaseHelpers.ts +0 -0
- package/src/application/auth/use-cases/SignInUseCaseMain.ts +0 -0
- package/src/application/auth/use-cases/SignInUseCase_part_aa +0 -150
- package/src/application/auth/use-cases/SignInUseCase_part_ab +0 -103
- package/src/application/auth/use-cases/SignOutUseCase.ts.bak +0 -288
- package/src/application/auth/use-cases/SignOutUseCaseCleanup.ts +0 -0
- package/src/application/auth/use-cases/SignOutUseCaseMain.ts +0 -0
- package/src/application/auth/use-cases/SignOutUseCase_part_aa +0 -150
- package/src/application/auth/use-cases/SignOutUseCase_part_ab +0 -138
- package/src/domains/account-deletion/domain/services/UserValidationHelpers.ts.bak +0 -181
- package/src/domains/account-deletion/domain/services/UserValidationHelpers_part_aa +0 -150
- package/src/domains/account-deletion/domain/services/UserValidationHelpers_part_ab +0 -31
- package/src/domains/account-deletion/domain/services/UserValidationService.ts.bak +0 -286
- package/src/domains/account-deletion/domain/services/UserValidationService_part_aa +0 -150
- package/src/domains/account-deletion/domain/services/UserValidationService_part_ab +0 -136
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor.ts.bak +0 -230
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor_part_aa +0 -150
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor_part_ab +0 -80
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionReauthHandler.ts.bak +0 -174
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionReauthHandler_part_aa +0 -150
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionReauthHandler_part_ab +0 -24
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionRepository.ts.bak +0 -266
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionRepository_part_aa +0 -150
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionRepository_part_ab +0 -116
- package/src/domains/account-deletion/infrastructure/services/reauthentication.service.ts.bak +0 -160
- package/src/domains/account-deletion/infrastructure/services/reauthentication.service_part_aa +0 -150
- package/src/domains/account-deletion/infrastructure/services/reauthentication.service_part_ab +0 -10
- package/src/domains/auth/infrastructure.ts.bak +0 -156
- package/src/domains/auth/infrastructure_part_aa +0 -150
- package/src/domains/auth/infrastructure_part_ab +0 -6
- package/src/domains/auth/presentation/hooks/GoogleOAuthHelpers.ts +0 -0
- package/src/domains/auth/presentation/hooks/GoogleOAuthHookService.ts.bak +0 -247
- package/src/domains/auth/presentation/hooks/GoogleOAuthHookService_part_aa +0 -150
- package/src/domains/auth/presentation/hooks/GoogleOAuthHookService_part_ab +0 -97
- package/src/domains/auth/presentation/hooks/GoogleOAuthService.ts +0 -0
- package/src/domains/firestore/domain/entities/Collection.ts.bak +0 -288
- package/src/domains/firestore/domain/entities/Collection_part_aa +0 -150
- package/src/domains/firestore/domain/entities/Collection_part_ab +0 -138
- package/src/domains/firestore/domain/entities/Document.ts.bak +0 -233
- package/src/domains/firestore/domain/entities/DocumentHelpers.ts +0 -0
- package/src/domains/firestore/domain/entities/DocumentMain.ts +0 -0
- package/src/domains/firestore/domain/entities/Document_part_aa +0 -150
- package/src/domains/firestore/domain/entities/Document_part_ab +0 -83
- package/src/domains/firestore/domain/services/QueryService.ts.bak +0 -182
- package/src/domains/firestore/domain/services/QueryServiceAnalysis.ts.bak +0 -169
- package/src/domains/firestore/domain/services/QueryServiceAnalysis_part_aa +0 -150
- package/src/domains/firestore/domain/services/QueryServiceAnalysis_part_ab +0 -19
- package/src/domains/firestore/domain/services/QueryServiceHelpers.ts.bak +0 -151
- package/src/domains/firestore/domain/services/QueryServiceHelpers_part_aa +0 -150
- package/src/domains/firestore/domain/services/QueryServiceHelpers_part_ab +0 -1
- package/src/domains/firestore/domain/services/QueryService_part_aa +0 -150
- package/src/domains/firestore/domain/services/QueryService_part_ab +0 -32
- package/src/domains/firestore/domain/value-objects/QueryOptionsSerialization.ts.bak +0 -207
- package/src/domains/firestore/domain/value-objects/QueryOptionsSerialization_part_aa +0 -150
- package/src/domains/firestore/domain/value-objects/QueryOptionsSerialization_part_ab +0 -57
- package/src/domains/firestore/domain/value-objects/QueryOptionsValidation.ts.bak +0 -182
- package/src/domains/firestore/domain/value-objects/QueryOptionsValidation_part_aa +0 -150
- package/src/domains/firestore/domain/value-objects/QueryOptionsValidation_part_ab +0 -32
- package/src/domains/firestore/domain/value-objects/QueryOptions_part_aa +0 -150
- package/src/domains/firestore/domain/value-objects/QueryOptions_part_ab +0 -41
- package/src/domains/firestore/domain/value-objects/WhereClause.ts.bak +0 -299
- package/src/domains/firestore/domain/value-objects/WhereClauseFactory.ts.bak +0 -207
- package/src/domains/firestore/domain/value-objects/WhereClauseFactory_part_aa +0 -150
- package/src/domains/firestore/domain/value-objects/WhereClauseFactory_part_ab +0 -57
- package/src/domains/firestore/domain/value-objects/WhereClause_part_aa +0 -150
- package/src/domains/firestore/domain/value-objects/WhereClause_part_ab +0 -149
- package/src/shared/infrastructure/base/ErrorHandler.ts.bak +0 -189
- package/src/shared/infrastructure/base/ErrorHandler_part_aa +0 -150
- package/src/shared/infrastructure/base/ErrorHandler_part_ab +0 -39
- package/src/shared/infrastructure/base/ServiceBase.ts.bak +0 -220
- package/src/shared/infrastructure/base/ServiceBase_part_aa +0 -150
- package/src/shared/infrastructure/base/ServiceBase_part_ab +0 -70
- package/src/shared/infrastructure/config/base/ServiceClientSingleton.ts.bak +0 -155
- package/src/shared/infrastructure/config/base/ServiceClientSingleton_part_aa +0 -150
- package/src/shared/infrastructure/config/base/ServiceClientSingleton_part_ab +0 -5
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
error: {
|
|
2
|
-
code: 'auth/not-signed-in',
|
|
3
|
-
message: 'No user is currently signed in',
|
|
4
|
-
},
|
|
5
|
-
};
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
// Additional checks can be added here
|
|
9
|
-
// For example: check for unsaved changes, active operations, etc.
|
|
10
|
-
|
|
11
|
-
return { success: true };
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Sign out with confirmation
|
|
16
|
-
* Shows confirmation dialog before signing out
|
|
17
|
-
*/
|
|
18
|
-
async signOutWithConfirmation(): Promise<SignOutUseCaseResult> {
|
|
19
|
-
const confirmed = await this.confirmSignOut();
|
|
20
|
-
|
|
21
|
-
if (!confirmed) {
|
|
22
|
-
return {
|
|
23
|
-
success: false,
|
|
24
|
-
error: {
|
|
25
|
-
code: 'auth/sign-out-cancelled',
|
|
26
|
-
message: 'Sign out was cancelled',
|
|
27
|
-
},
|
|
28
|
-
wasSignedIn: this.isSignedIn(),
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return this.execute();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Sign out and navigate
|
|
37
|
-
* Signs out and navigates to sign in screen
|
|
38
|
-
*/
|
|
39
|
-
async signOutAndNavigate(): Promise<SignOutUseCaseResult> {
|
|
40
|
-
return this.execute({
|
|
41
|
-
clearLocalData: true,
|
|
42
|
-
navigateToSignIn: true,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Force sign out
|
|
48
|
-
* Signs out even if there are errors
|
|
49
|
-
*/
|
|
50
|
-
async forceSignOut(): Promise<void> {
|
|
51
|
-
try {
|
|
52
|
-
await this.execute({
|
|
53
|
-
clearLocalData: true,
|
|
54
|
-
});
|
|
55
|
-
} catch (error) {
|
|
56
|
-
// Ignore errors during force sign out
|
|
57
|
-
if (__DEV__) {
|
|
58
|
-
console.error('[SignOutUseCase] Force sign out error:', error);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Ensure local data is cleared
|
|
63
|
-
await this.clearLocalData();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Get sign out statistics
|
|
68
|
-
*/
|
|
69
|
-
getSignOutStats(): {
|
|
70
|
-
readonly isSignedIn: boolean;
|
|
71
|
-
readonly isAnonymous: boolean;
|
|
72
|
-
readonly hasUserId: boolean;
|
|
73
|
-
} {
|
|
74
|
-
return {
|
|
75
|
-
isSignedIn: this.isSignedIn(),
|
|
76
|
-
isAnonymous: this.isAnonymous(),
|
|
77
|
-
hasUserId: this.getCurrentUserId() !== null,
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Create sign out options
|
|
83
|
-
*/
|
|
84
|
-
createOptions(options: Partial<SignOutOptions> = {}): SignOutOptions {
|
|
85
|
-
return {
|
|
86
|
-
clearLocalData: false,
|
|
87
|
-
navigateToSignIn: false,
|
|
88
|
-
showConfirmation: false,
|
|
89
|
-
...options,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Quick sign out helper
|
|
95
|
-
*/
|
|
96
|
-
async quickSignOut(): Promise<SignOutUseCaseResult> {
|
|
97
|
-
return this.execute();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Check if confirmation should be shown
|
|
102
|
-
*/
|
|
103
|
-
shouldShowConfirmation(): boolean {
|
|
104
|
-
// Default: show confirmation for authenticated users
|
|
105
|
-
return this.isSignedIn() && !this.isAnonymous();
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Get user-friendly sign out message
|
|
110
|
-
*/
|
|
111
|
-
getSignOutMessage(): string {
|
|
112
|
-
if (!this.isSignedIn()) {
|
|
113
|
-
return 'You are not signed in';
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (this.isAnonymous()) {
|
|
117
|
-
return 'Sign out from guest session?';
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return 'Are you sure you want to sign out?';
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Factory function to create sign out use case
|
|
126
|
-
*/
|
|
127
|
-
export function createSignOutUseCase(authPort: IAuthPort): SignOutUseCase {
|
|
128
|
-
return new SignOutUseCase(authPort);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Factory function to create sign out use case with default auth port
|
|
133
|
-
*/
|
|
134
|
-
export async function createDefaultSignOutUseCase(): Promise<SignOutUseCase> {
|
|
135
|
-
const { createAuthPort } = await import('../ports/AuthPort');
|
|
136
|
-
const authPort = createAuthPort();
|
|
137
|
-
return createSignOutUseCase(authPort);
|
|
138
|
-
}
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* User Validation Helpers
|
|
3
|
-
* Single Responsibility: Provide helper methods for user validation
|
|
4
|
-
*
|
|
5
|
-
* Helper methods separated from main UserValidationService.
|
|
6
|
-
* Provides utility functions for user state checking.
|
|
7
|
-
*
|
|
8
|
-
* Max lines: 150 (enforced for maintainability)
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { User } from 'firebase/auth';
|
|
12
|
-
import type { UserValidationService } from './UserValidationService';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Check if user email matches pattern
|
|
16
|
-
*/
|
|
17
|
-
export function isValidEmailFormat(email: string): boolean {
|
|
18
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
19
|
-
return emailRegex.test(email);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Get password strength indicator
|
|
24
|
-
*/
|
|
25
|
-
export function getPasswordStrength(password: string): 'weak' | 'medium' | 'strong' {
|
|
26
|
-
if (password.length < 6) {
|
|
27
|
-
return 'weak';
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (password.length < 8) {
|
|
31
|
-
return 'medium';
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Check for variety
|
|
35
|
-
const hasLower = /[a-z]/.test(password);
|
|
36
|
-
const hasUpper = /[A-Z]/.test(password);
|
|
37
|
-
const hasNumber = /[0-9]/.test(password);
|
|
38
|
-
const hasSpecial = /[^a-zA-Z0-9]/.test(password);
|
|
39
|
-
|
|
40
|
-
const varietyScore = [hasLower, hasUpper, hasNumber, hasSpecial].filter(Boolean).length;
|
|
41
|
-
|
|
42
|
-
if (varietyScore >= 3) {
|
|
43
|
-
return 'strong';
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return 'medium';
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Check if account is locked
|
|
51
|
-
*/
|
|
52
|
-
export function isAccountLocked(errorCode?: string): boolean {
|
|
53
|
-
return errorCode === 'auth/too-many-requests' || errorCode === 'auth/user-disabled';
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Get user-friendly error message
|
|
58
|
-
*/
|
|
59
|
-
export function getAuthErrorMessage(errorCode: string): string {
|
|
60
|
-
const errorMessages: Record<string, string> = {
|
|
61
|
-
'auth/invalid-credentials': 'Invalid email or password',
|
|
62
|
-
'auth/user-not-found': 'No account found with this email',
|
|
63
|
-
'auth/wrong-password': 'Incorrect password',
|
|
64
|
-
'auth/unverified-email': 'Please verify your email first',
|
|
65
|
-
'auth/user-disabled': 'This account has been disabled',
|
|
66
|
-
'auth/too-many-requests': 'Too many attempts. Please try again later',
|
|
67
|
-
'auth/invalid-email': 'Invalid email address',
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
return errorMessages[errorCode] || 'Authentication failed. Please try again.';
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Check if user session is valid
|
|
75
|
-
*/
|
|
76
|
-
export function isSessionValid(user: User, maxAgeMs: number = 30 * 60 * 1000): boolean {
|
|
77
|
-
if (!user.metadata.lastSignInTime) {
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const lastSignIn = new Date(user.metadata.lastSignInTime).getTime();
|
|
82
|
-
const timeSinceSignIn = Date.now() - lastSignIn;
|
|
83
|
-
|
|
84
|
-
return timeSinceSignIn <= maxAgeMs;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Check if user needs to refresh session
|
|
89
|
-
*/
|
|
90
|
-
export function needsSessionRefresh(user: User, maxAgeMs: number = 30 * 60 * 1000): boolean {
|
|
91
|
-
return !isSessionValid(user, maxAgeMs);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Get user display name
|
|
96
|
-
*/
|
|
97
|
-
export function getUserDisplayName(user: User): string {
|
|
98
|
-
if (user.displayName) {
|
|
99
|
-
return user.displayName;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (user.email) {
|
|
103
|
-
return user.email.split('@')[0];
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return 'User';
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Get user initials for avatar
|
|
111
|
-
*/
|
|
112
|
-
export function getUserInitials(user: User): string {
|
|
113
|
-
if (user.displayName) {
|
|
114
|
-
const names = user.displayName.split(' ');
|
|
115
|
-
if (names.length >= 2) {
|
|
116
|
-
return (names[0][0] + names[names.length - 1][0]).toUpperCase();
|
|
117
|
-
}
|
|
118
|
-
return names[0][0].toUpperCase();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (user.email) {
|
|
122
|
-
return user.email[0].toUpperCase();
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return 'U';
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Check if user profile is complete
|
|
130
|
-
*/
|
|
131
|
-
export function isProfileComplete(user: User): boolean {
|
|
132
|
-
return !!(
|
|
133
|
-
user.email &&
|
|
134
|
-
user.displayName &&
|
|
135
|
-
user.emailVerified &&
|
|
136
|
-
user.metadata.lastSignInTime
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Get profile completion percentage
|
|
142
|
-
*/
|
|
143
|
-
export function getProfileCompletionPercentage(user: User): number {
|
|
144
|
-
let completion = 0;
|
|
145
|
-
|
|
146
|
-
if (user.email) completion += 25;
|
|
147
|
-
if (user.displayName) completion += 25;
|
|
148
|
-
if (user.emailVerified) completion += 25;
|
|
149
|
-
if (user.metadata.lastSignInTime) completion += 25;
|
|
150
|
-
|
|
151
|
-
return completion;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Check if user can perform sensitive operation
|
|
156
|
-
*/
|
|
157
|
-
export function canPerformSensitiveOperation(user: User, maxSessionAgeMs: number = 5 * 60 * 1000): boolean {
|
|
158
|
-
return isSessionValid(user, maxSessionAgeMs);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Get user account age in days
|
|
163
|
-
*/
|
|
164
|
-
export function getAccountAgeDays(user: User): number | null {
|
|
165
|
-
if (!user.metadata.creationTime) {
|
|
166
|
-
return null;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const creationTime = new Date(user.metadata.creationTime).getTime();
|
|
170
|
-
const ageMs = Date.now() - creationTime;
|
|
171
|
-
|
|
172
|
-
return Math.floor(ageMs / (24 * 60 * 60 * 1000));
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Check if account is old enough for operation
|
|
177
|
-
*/
|
|
178
|
-
export function isAccountOldEnough(user: User, minDays: number = 1): boolean {
|
|
179
|
-
const ageDays = getAccountAgeDays(user);
|
|
180
|
-
return ageDays !== null && ageDays >= minDays;
|
|
181
|
-
}
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* User Validation Helpers
|
|
3
|
-
* Single Responsibility: Provide helper methods for user validation
|
|
4
|
-
*
|
|
5
|
-
* Helper methods separated from main UserValidationService.
|
|
6
|
-
* Provides utility functions for user state checking.
|
|
7
|
-
*
|
|
8
|
-
* Max lines: 150 (enforced for maintainability)
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { User } from 'firebase/auth';
|
|
12
|
-
import type { UserValidationService } from './UserValidationService';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Check if user email matches pattern
|
|
16
|
-
*/
|
|
17
|
-
export function isValidEmailFormat(email: string): boolean {
|
|
18
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
19
|
-
return emailRegex.test(email);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Get password strength indicator
|
|
24
|
-
*/
|
|
25
|
-
export function getPasswordStrength(password: string): 'weak' | 'medium' | 'strong' {
|
|
26
|
-
if (password.length < 6) {
|
|
27
|
-
return 'weak';
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (password.length < 8) {
|
|
31
|
-
return 'medium';
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Check for variety
|
|
35
|
-
const hasLower = /[a-z]/.test(password);
|
|
36
|
-
const hasUpper = /[A-Z]/.test(password);
|
|
37
|
-
const hasNumber = /[0-9]/.test(password);
|
|
38
|
-
const hasSpecial = /[^a-zA-Z0-9]/.test(password);
|
|
39
|
-
|
|
40
|
-
const varietyScore = [hasLower, hasUpper, hasNumber, hasSpecial].filter(Boolean).length;
|
|
41
|
-
|
|
42
|
-
if (varietyScore >= 3) {
|
|
43
|
-
return 'strong';
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return 'medium';
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Check if account is locked
|
|
51
|
-
*/
|
|
52
|
-
export function isAccountLocked(errorCode?: string): boolean {
|
|
53
|
-
return errorCode === 'auth/too-many-requests' || errorCode === 'auth/user-disabled';
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Get user-friendly error message
|
|
58
|
-
*/
|
|
59
|
-
export function getAuthErrorMessage(errorCode: string): string {
|
|
60
|
-
const errorMessages: Record<string, string> = {
|
|
61
|
-
'auth/invalid-credentials': 'Invalid email or password',
|
|
62
|
-
'auth/user-not-found': 'No account found with this email',
|
|
63
|
-
'auth/wrong-password': 'Incorrect password',
|
|
64
|
-
'auth/unverified-email': 'Please verify your email first',
|
|
65
|
-
'auth/user-disabled': 'This account has been disabled',
|
|
66
|
-
'auth/too-many-requests': 'Too many attempts. Please try again later',
|
|
67
|
-
'auth/invalid-email': 'Invalid email address',
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
return errorMessages[errorCode] || 'Authentication failed. Please try again.';
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Check if user session is valid
|
|
75
|
-
*/
|
|
76
|
-
export function isSessionValid(user: User, maxAgeMs: number = 30 * 60 * 1000): boolean {
|
|
77
|
-
if (!user.metadata.lastSignInTime) {
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const lastSignIn = new Date(user.metadata.lastSignInTime).getTime();
|
|
82
|
-
const timeSinceSignIn = Date.now() - lastSignIn;
|
|
83
|
-
|
|
84
|
-
return timeSinceSignIn <= maxAgeMs;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Check if user needs to refresh session
|
|
89
|
-
*/
|
|
90
|
-
export function needsSessionRefresh(user: User, maxAgeMs: number = 30 * 60 * 1000): boolean {
|
|
91
|
-
return !isSessionValid(user, maxAgeMs);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Get user display name
|
|
96
|
-
*/
|
|
97
|
-
export function getUserDisplayName(user: User): string {
|
|
98
|
-
if (user.displayName) {
|
|
99
|
-
return user.displayName;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (user.email) {
|
|
103
|
-
return user.email.split('@')[0];
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return 'User';
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Get user initials for avatar
|
|
111
|
-
*/
|
|
112
|
-
export function getUserInitials(user: User): string {
|
|
113
|
-
if (user.displayName) {
|
|
114
|
-
const names = user.displayName.split(' ');
|
|
115
|
-
if (names.length >= 2) {
|
|
116
|
-
return (names[0][0] + names[names.length - 1][0]).toUpperCase();
|
|
117
|
-
}
|
|
118
|
-
return names[0][0].toUpperCase();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (user.email) {
|
|
122
|
-
return user.email[0].toUpperCase();
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return 'U';
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Check if user profile is complete
|
|
130
|
-
*/
|
|
131
|
-
export function isProfileComplete(user: User): boolean {
|
|
132
|
-
return !!(
|
|
133
|
-
user.email &&
|
|
134
|
-
user.displayName &&
|
|
135
|
-
user.emailVerified &&
|
|
136
|
-
user.metadata.lastSignInTime
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Get profile completion percentage
|
|
142
|
-
*/
|
|
143
|
-
export function getProfileCompletionPercentage(user: User): number {
|
|
144
|
-
let completion = 0;
|
|
145
|
-
|
|
146
|
-
if (user.email) completion += 25;
|
|
147
|
-
if (user.displayName) completion += 25;
|
|
148
|
-
if (user.emailVerified) completion += 25;
|
|
149
|
-
if (user.metadata.lastSignInTime) completion += 25;
|
|
150
|
-
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
return completion;
|
|
2
|
-
}
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Check if user can perform sensitive operation
|
|
6
|
-
*/
|
|
7
|
-
export function canPerformSensitiveOperation(user: User, maxSessionAgeMs: number = 5 * 60 * 1000): boolean {
|
|
8
|
-
return isSessionValid(user, maxSessionAgeMs);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Get user account age in days
|
|
13
|
-
*/
|
|
14
|
-
export function getAccountAgeDays(user: User): number | null {
|
|
15
|
-
if (!user.metadata.creationTime) {
|
|
16
|
-
return null;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const creationTime = new Date(user.metadata.creationTime).getTime();
|
|
20
|
-
const ageMs = Date.now() - creationTime;
|
|
21
|
-
|
|
22
|
-
return Math.floor(ageMs / (24 * 60 * 60 * 1000));
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Check if account is old enough for operation
|
|
27
|
-
*/
|
|
28
|
-
export function isAccountOldEnough(user: User, minDays: number = 1): boolean {
|
|
29
|
-
const ageDays = getAccountAgeDays(user);
|
|
30
|
-
return ageDays !== null && ageDays >= minDays;
|
|
31
|
-
}
|