@umituz/react-native-firebase 2.6.3 → 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 +6 -2
- package/src/domains/firestore/domain/value-objects/WhereClause.ts +0 -14
- 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/QueryOptions.ts.bak +0 -191
- 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,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Auth Port
|
|
3
|
-
* Single Responsibility: Define authentication contract
|
|
4
|
-
*
|
|
5
|
-
* Port interface for authentication operations.
|
|
6
|
-
* Defines the contract that infrastructure must implement.
|
|
7
|
-
*
|
|
8
|
-
* Max lines: 150 (enforced for maintainability)
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { User, Auth } from 'firebase/auth';
|
|
12
|
-
import type { Result } from '../../../shared/domain/utils';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Email credentials
|
|
16
|
-
*/
|
|
17
|
-
export interface EmailCredentials {
|
|
18
|
-
readonly email: string;
|
|
19
|
-
readonly password: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Sign in result
|
|
24
|
-
*/
|
|
25
|
-
export interface SignInResult {
|
|
26
|
-
readonly user: User;
|
|
27
|
-
readonly isNewUser: boolean;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Sign up result
|
|
32
|
-
*/
|
|
33
|
-
export interface SignUpResult {
|
|
34
|
-
readonly user: User;
|
|
35
|
-
readonly userId: string;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Auth port interface
|
|
40
|
-
* Defines contract for authentication operations
|
|
41
|
-
*/
|
|
42
|
-
export interface IAuthPort {
|
|
43
|
-
/**
|
|
44
|
-
* Sign in with email and password
|
|
45
|
-
*/
|
|
46
|
-
signInWithEmail(credentials: EmailCredentials): Promise<Result<SignInResult>>;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Sign up with email and password
|
|
50
|
-
*/
|
|
51
|
-
signUpWithEmail(credentials: EmailCredentials): Promise<Result<SignUpResult>>;
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Sign out current user
|
|
55
|
-
*/
|
|
56
|
-
signOut(): Promise<Result<void>>;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Get current authenticated user
|
|
60
|
-
*/
|
|
61
|
-
getCurrentUser(): User | null;
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Get current user ID
|
|
65
|
-
*/
|
|
66
|
-
getCurrentUserId(): string | null;
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Check if user is authenticated
|
|
70
|
-
*/
|
|
71
|
-
isAuthenticated(): boolean;
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Check if user is anonymous
|
|
75
|
-
*/
|
|
76
|
-
isAnonymous(): boolean;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Delete user account
|
|
80
|
-
*/
|
|
81
|
-
deleteAccount(): Promise<Result<void>>;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Update user password
|
|
85
|
-
*/
|
|
86
|
-
updatePassword(newPassword: string): Promise<Result<void>>;
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Send password reset email
|
|
90
|
-
*/
|
|
91
|
-
sendPasswordResetEmail(email: string): Promise<Result<void>>;
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Get auth instance
|
|
95
|
-
*/
|
|
96
|
-
getAuth(): Auth | null;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Auth port options
|
|
101
|
-
*/
|
|
102
|
-
export interface AuthPortOptions {
|
|
103
|
-
/** Auto-initialize auth on first access */
|
|
104
|
-
autoInitialize?: boolean;
|
|
105
|
-
/** Enable detailed logging */
|
|
106
|
-
enableLogging?: boolean;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Auth port configuration
|
|
111
|
-
*/
|
|
112
|
-
export interface AuthPortConfig {
|
|
113
|
-
readonly port: IAuthPort;
|
|
114
|
-
readonly options: AuthPortOptions;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Create auth port configuration
|
|
119
|
-
*/
|
|
120
|
-
export function createAuthPortConfig(
|
|
121
|
-
port: IAuthPort,
|
|
122
|
-
options: AuthPortOptions = {}
|
|
123
|
-
): AuthPortConfig {
|
|
124
|
-
return {
|
|
125
|
-
port,
|
|
126
|
-
options: {
|
|
127
|
-
autoInitialize: true,
|
|
128
|
-
enableLogging: __DEV__,
|
|
129
|
-
...options,
|
|
130
|
-
},
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Auth port factory
|
|
136
|
-
* Creates auth port instances
|
|
137
|
-
*/
|
|
138
|
-
export interface IAuthPortFactory {
|
|
139
|
-
createPort(options?: AuthPortOptions): IAuthPort;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Default auth port factory
|
|
144
|
-
* Implements factory pattern for auth ports
|
|
145
|
-
*/
|
|
146
|
-
export class AuthPortFactory implements IAuthPortFactory {
|
|
147
|
-
createPort(options?: AuthPortOptions): IAuthPort {
|
|
148
|
-
// Import and create actual implementation
|
|
149
|
-
const { FirebaseAuthPort } = require('../implementations/FirebaseAuthPort');
|
|
150
|
-
return new FirebaseAuthPort(options);
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
}
|
|
2
|
-
}
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Default auth port factory instance
|
|
6
|
-
*/
|
|
7
|
-
export const authPortFactory = new AuthPortFactory();
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Create auth port with default factory
|
|
11
|
-
*/
|
|
12
|
-
export function createAuthPort(options?: AuthPortOptions): IAuthPort {
|
|
13
|
-
return authPortFactory.createPort(options);
|
|
14
|
-
}
|
|
@@ -1,253 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sign In Use Case
|
|
3
|
-
* Single Responsibility: Handle user sign in operations
|
|
4
|
-
*
|
|
5
|
-
* Application use case for user authentication.
|
|
6
|
-
* Coordinates domain services and infrastructure.
|
|
7
|
-
*
|
|
8
|
-
* Max lines: 150 (enforced for maintainability)
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { User } from 'firebase/auth';
|
|
12
|
-
import type { Result } from '../../../shared/domain/utils';
|
|
13
|
-
import type { IAuthPort, EmailCredentials, SignInResult } from '../ports/AuthPort';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Sign in use case result
|
|
17
|
-
*/
|
|
18
|
-
export interface SignInUseCaseResult extends Result<SignInResult> {
|
|
19
|
-
readonly requiresVerification?: boolean;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Sign in use case options
|
|
24
|
-
*/
|
|
25
|
-
export interface SignInOptions {
|
|
26
|
-
/** Email credentials */
|
|
27
|
-
readonly email: string;
|
|
28
|
-
/** Password */
|
|
29
|
-
readonly password: string;
|
|
30
|
-
/** Remember user */
|
|
31
|
-
readonly rememberMe?: boolean;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Sign in use case
|
|
36
|
-
* Handles user sign in with validation and error handling
|
|
37
|
-
*/
|
|
38
|
-
export class SignInUseCase {
|
|
39
|
-
private readonly authPort: IAuthPort;
|
|
40
|
-
|
|
41
|
-
constructor(authPort: IAuthPort) {
|
|
42
|
-
this.authPort = authPort;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Execute sign in use case
|
|
47
|
-
* Validates credentials and signs in user
|
|
48
|
-
*/
|
|
49
|
-
async execute(options: SignInOptions): Promise<SignInUseCaseResult> {
|
|
50
|
-
// Validate credentials
|
|
51
|
-
const validation = this.validateCredentials(options);
|
|
52
|
-
if (!validation.valid) {
|
|
53
|
-
return {
|
|
54
|
-
success: false,
|
|
55
|
-
error: {
|
|
56
|
-
code: 'auth/invalid-credentials',
|
|
57
|
-
message: validation.error,
|
|
58
|
-
},
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Create credentials object
|
|
63
|
-
const credentials: EmailCredentials = {
|
|
64
|
-
email: options.email,
|
|
65
|
-
password: options.password,
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
// Sign in with credentials
|
|
69
|
-
const result = await this.authPort.signInWithEmail(credentials);
|
|
70
|
-
|
|
71
|
-
if (!result.success) {
|
|
72
|
-
return {
|
|
73
|
-
success: false,
|
|
74
|
-
error: result.error,
|
|
75
|
-
requiresVerification: this.requiresVerification(result.error?.code),
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return {
|
|
80
|
-
success: true,
|
|
81
|
-
data: result.data,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Validate email and password
|
|
87
|
-
*/
|
|
88
|
-
private validateCredentials(options: SignInOptions): { valid: boolean; error?: string } {
|
|
89
|
-
const { email, password } = options;
|
|
90
|
-
|
|
91
|
-
// Validate email
|
|
92
|
-
if (!email || typeof email !== 'string' || email.trim() === '') {
|
|
93
|
-
return { valid: false, error: 'Email is required' };
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
97
|
-
if (!emailRegex.test(email)) {
|
|
98
|
-
return { valid: false, error: 'Invalid email format' };
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Validate password
|
|
102
|
-
if (!password || typeof password !== 'string' || password.trim() === '') {
|
|
103
|
-
return { valid: false, error: 'Password is required' };
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (password.length < 6) {
|
|
107
|
-
return { valid: false, error: 'Password must be at least 6 characters' };
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return { valid: true };
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Check if error requires email verification
|
|
115
|
-
*/
|
|
116
|
-
private requiresVerification(errorCode?: string): boolean {
|
|
117
|
-
return errorCode === 'auth/unverified-email' || errorCode === 'auth/email-not-verified';
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Check if user is already signed in
|
|
122
|
-
*/
|
|
123
|
-
isSignedIn(): boolean {
|
|
124
|
-
return this.authPort.isAuthenticated();
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Get current user
|
|
129
|
-
*/
|
|
130
|
-
getCurrentUser(): User | null {
|
|
131
|
-
return this.authPort.getCurrentUser();
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Sign out current user
|
|
136
|
-
*/
|
|
137
|
-
async signOut(): Promise<Result<void>> {
|
|
138
|
-
return this.authPort.signOut();
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Check if credentials match current user
|
|
143
|
-
*/
|
|
144
|
-
async credentialsMatchCurrentUser(email: string): Promise<boolean> {
|
|
145
|
-
const currentUser = this.getCurrentUser();
|
|
146
|
-
if (!currentUser || !currentUser.email) {
|
|
147
|
-
return false;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return currentUser.email.toLowerCase() === email.toLowerCase();
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Validate email format
|
|
155
|
-
*/
|
|
156
|
-
isValidEmail(email: string): boolean {
|
|
157
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
158
|
-
return emailRegex.test(email);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Validate password strength
|
|
163
|
-
*/
|
|
164
|
-
isStrongPassword(password: string): boolean {
|
|
165
|
-
// Basic password strength check
|
|
166
|
-
return password.length >= 8;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Get password strength indicator
|
|
171
|
-
*/
|
|
172
|
-
getPasswordStrength(password: string): 'weak' | 'medium' | 'strong' {
|
|
173
|
-
if (password.length < 6) {
|
|
174
|
-
return 'weak';
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (password.length < 8) {
|
|
178
|
-
return 'medium';
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Check for variety
|
|
182
|
-
const hasLower = /[a-z]/.test(password);
|
|
183
|
-
const hasUpper = /[A-Z]/.test(password);
|
|
184
|
-
const hasNumber = /[0-9]/.test(password);
|
|
185
|
-
const hasSpecial = /[^a-zA-Z0-9]/.test(password);
|
|
186
|
-
|
|
187
|
-
const varietyScore = [hasLower, hasUpper, hasNumber, hasSpecial].filter(Boolean).length;
|
|
188
|
-
|
|
189
|
-
if (varietyScore >= 3) {
|
|
190
|
-
return 'strong';
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return 'medium';
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Check if account is locked
|
|
198
|
-
*/
|
|
199
|
-
isAccountLocked(errorCode?: string): boolean {
|
|
200
|
-
return errorCode === 'auth/too-many-requests' || errorCode === 'auth/user-disabled';
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Get user-friendly error message
|
|
205
|
-
*/
|
|
206
|
-
getErrorMessage(errorCode: string): string {
|
|
207
|
-
const errorMessages: Record<string, string> = {
|
|
208
|
-
'auth/invalid-credentials': 'Invalid email or password',
|
|
209
|
-
'auth/user-not-found': 'No account found with this email',
|
|
210
|
-
'auth/wrong-password': 'Incorrect password',
|
|
211
|
-
'auth/unverified-email': 'Please verify your email first',
|
|
212
|
-
'auth/user-disabled': 'This account has been disabled',
|
|
213
|
-
'auth/too-many-requests': 'Too many attempts. Please try again later',
|
|
214
|
-
'auth/invalid-email': 'Invalid email address',
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
return errorMessages[errorCode] || 'Sign in failed. Please try again.';
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Create sign in options from email and password
|
|
222
|
-
*/
|
|
223
|
-
createOptions(email: string, password: string, rememberMe: boolean = false): SignInOptions {
|
|
224
|
-
return {
|
|
225
|
-
email,
|
|
226
|
-
password,
|
|
227
|
-
rememberMe,
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Quick sign in helper
|
|
233
|
-
*/
|
|
234
|
-
async quickSignIn(email: string, password: string): Promise<SignInUseCaseResult> {
|
|
235
|
-
return this.execute(this.createOptions(email, password));
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Factory function to create sign in use case
|
|
241
|
-
*/
|
|
242
|
-
export function createSignInUseCase(authPort: IAuthPort): SignInUseCase {
|
|
243
|
-
return new SignInUseCase(authPort);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Factory function to create sign in use case with default auth port
|
|
248
|
-
*/
|
|
249
|
-
export async function createDefaultSignInUseCase(): Promise<SignInUseCase> {
|
|
250
|
-
const { createAuthPort } = await import('../ports/AuthPort');
|
|
251
|
-
const authPort = createAuthPort();
|
|
252
|
-
return createSignInUseCase(authPort);
|
|
253
|
-
}
|
|
File without changes
|
|
File without changes
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sign In Use Case
|
|
3
|
-
* Single Responsibility: Handle user sign in operations
|
|
4
|
-
*
|
|
5
|
-
* Application use case for user authentication.
|
|
6
|
-
* Coordinates domain services and infrastructure.
|
|
7
|
-
*
|
|
8
|
-
* Max lines: 150 (enforced for maintainability)
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { User } from 'firebase/auth';
|
|
12
|
-
import type { Result } from '../../../shared/domain/utils';
|
|
13
|
-
import type { IAuthPort, EmailCredentials, SignInResult } from '../ports/AuthPort';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Sign in use case result
|
|
17
|
-
*/
|
|
18
|
-
export interface SignInUseCaseResult extends Result<SignInResult> {
|
|
19
|
-
readonly requiresVerification?: boolean;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Sign in use case options
|
|
24
|
-
*/
|
|
25
|
-
export interface SignInOptions {
|
|
26
|
-
/** Email credentials */
|
|
27
|
-
readonly email: string;
|
|
28
|
-
/** Password */
|
|
29
|
-
readonly password: string;
|
|
30
|
-
/** Remember user */
|
|
31
|
-
readonly rememberMe?: boolean;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Sign in use case
|
|
36
|
-
* Handles user sign in with validation and error handling
|
|
37
|
-
*/
|
|
38
|
-
export class SignInUseCase {
|
|
39
|
-
private readonly authPort: IAuthPort;
|
|
40
|
-
|
|
41
|
-
constructor(authPort: IAuthPort) {
|
|
42
|
-
this.authPort = authPort;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Execute sign in use case
|
|
47
|
-
* Validates credentials and signs in user
|
|
48
|
-
*/
|
|
49
|
-
async execute(options: SignInOptions): Promise<SignInUseCaseResult> {
|
|
50
|
-
// Validate credentials
|
|
51
|
-
const validation = this.validateCredentials(options);
|
|
52
|
-
if (!validation.valid) {
|
|
53
|
-
return {
|
|
54
|
-
success: false,
|
|
55
|
-
error: {
|
|
56
|
-
code: 'auth/invalid-credentials',
|
|
57
|
-
message: validation.error,
|
|
58
|
-
},
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Create credentials object
|
|
63
|
-
const credentials: EmailCredentials = {
|
|
64
|
-
email: options.email,
|
|
65
|
-
password: options.password,
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
// Sign in with credentials
|
|
69
|
-
const result = await this.authPort.signInWithEmail(credentials);
|
|
70
|
-
|
|
71
|
-
if (!result.success) {
|
|
72
|
-
return {
|
|
73
|
-
success: false,
|
|
74
|
-
error: result.error,
|
|
75
|
-
requiresVerification: this.requiresVerification(result.error?.code),
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return {
|
|
80
|
-
success: true,
|
|
81
|
-
data: result.data,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Validate email and password
|
|
87
|
-
*/
|
|
88
|
-
private validateCredentials(options: SignInOptions): { valid: boolean; error?: string } {
|
|
89
|
-
const { email, password } = options;
|
|
90
|
-
|
|
91
|
-
// Validate email
|
|
92
|
-
if (!email || typeof email !== 'string' || email.trim() === '') {
|
|
93
|
-
return { valid: false, error: 'Email is required' };
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
97
|
-
if (!emailRegex.test(email)) {
|
|
98
|
-
return { valid: false, error: 'Invalid email format' };
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Validate password
|
|
102
|
-
if (!password || typeof password !== 'string' || password.trim() === '') {
|
|
103
|
-
return { valid: false, error: 'Password is required' };
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (password.length < 6) {
|
|
107
|
-
return { valid: false, error: 'Password must be at least 6 characters' };
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return { valid: true };
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Check if error requires email verification
|
|
115
|
-
*/
|
|
116
|
-
private requiresVerification(errorCode?: string): boolean {
|
|
117
|
-
return errorCode === 'auth/unverified-email' || errorCode === 'auth/email-not-verified';
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Check if user is already signed in
|
|
122
|
-
*/
|
|
123
|
-
isSignedIn(): boolean {
|
|
124
|
-
return this.authPort.isAuthenticated();
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Get current user
|
|
129
|
-
*/
|
|
130
|
-
getCurrentUser(): User | null {
|
|
131
|
-
return this.authPort.getCurrentUser();
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Sign out current user
|
|
136
|
-
*/
|
|
137
|
-
async signOut(): Promise<Result<void>> {
|
|
138
|
-
return this.authPort.signOut();
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Check if credentials match current user
|
|
143
|
-
*/
|
|
144
|
-
async credentialsMatchCurrentUser(email: string): Promise<boolean> {
|
|
145
|
-
const currentUser = this.getCurrentUser();
|
|
146
|
-
if (!currentUser || !currentUser.email) {
|
|
147
|
-
return false;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return currentUser.email.toLowerCase() === email.toLowerCase();
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
}
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Validate email format
|
|
5
|
-
*/
|
|
6
|
-
isValidEmail(email: string): boolean {
|
|
7
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
8
|
-
return emailRegex.test(email);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Validate password strength
|
|
13
|
-
*/
|
|
14
|
-
isStrongPassword(password: string): boolean {
|
|
15
|
-
// Basic password strength check
|
|
16
|
-
return password.length >= 8;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Get password strength indicator
|
|
21
|
-
*/
|
|
22
|
-
getPasswordStrength(password: string): 'weak' | 'medium' | 'strong' {
|
|
23
|
-
if (password.length < 6) {
|
|
24
|
-
return 'weak';
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (password.length < 8) {
|
|
28
|
-
return 'medium';
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Check for variety
|
|
32
|
-
const hasLower = /[a-z]/.test(password);
|
|
33
|
-
const hasUpper = /[A-Z]/.test(password);
|
|
34
|
-
const hasNumber = /[0-9]/.test(password);
|
|
35
|
-
const hasSpecial = /[^a-zA-Z0-9]/.test(password);
|
|
36
|
-
|
|
37
|
-
const varietyScore = [hasLower, hasUpper, hasNumber, hasSpecial].filter(Boolean).length;
|
|
38
|
-
|
|
39
|
-
if (varietyScore >= 3) {
|
|
40
|
-
return 'strong';
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return 'medium';
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Check if account is locked
|
|
48
|
-
*/
|
|
49
|
-
isAccountLocked(errorCode?: string): boolean {
|
|
50
|
-
return errorCode === 'auth/too-many-requests' || errorCode === 'auth/user-disabled';
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Get user-friendly error message
|
|
55
|
-
*/
|
|
56
|
-
getErrorMessage(errorCode: string): string {
|
|
57
|
-
const errorMessages: Record<string, string> = {
|
|
58
|
-
'auth/invalid-credentials': 'Invalid email or password',
|
|
59
|
-
'auth/user-not-found': 'No account found with this email',
|
|
60
|
-
'auth/wrong-password': 'Incorrect password',
|
|
61
|
-
'auth/unverified-email': 'Please verify your email first',
|
|
62
|
-
'auth/user-disabled': 'This account has been disabled',
|
|
63
|
-
'auth/too-many-requests': 'Too many attempts. Please try again later',
|
|
64
|
-
'auth/invalid-email': 'Invalid email address',
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
return errorMessages[errorCode] || 'Sign in failed. Please try again.';
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Create sign in options from email and password
|
|
72
|
-
*/
|
|
73
|
-
createOptions(email: string, password: string, rememberMe: boolean = false): SignInOptions {
|
|
74
|
-
return {
|
|
75
|
-
email,
|
|
76
|
-
password,
|
|
77
|
-
rememberMe,
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Quick sign in helper
|
|
83
|
-
*/
|
|
84
|
-
async quickSignIn(email: string, password: string): Promise<SignInUseCaseResult> {
|
|
85
|
-
return this.execute(this.createOptions(email, password));
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Factory function to create sign in use case
|
|
91
|
-
*/
|
|
92
|
-
export function createSignInUseCase(authPort: IAuthPort): SignInUseCase {
|
|
93
|
-
return new SignInUseCase(authPort);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Factory function to create sign in use case with default auth port
|
|
98
|
-
*/
|
|
99
|
-
export async function createDefaultSignInUseCase(): Promise<SignInUseCase> {
|
|
100
|
-
const { createAuthPort } = await import('../ports/AuthPort');
|
|
101
|
-
const authPort = createAuthPort();
|
|
102
|
-
return createSignInUseCase(authPort);
|
|
103
|
-
}
|