@umituz/react-native-auth 3.4.22 → 3.4.23

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.
@@ -1,38 +1,17 @@
1
- /**
2
- * Auth Validation Utilities
3
- * Single Responsibility: Email and password validation for authentication
4
- */
5
-
6
1
  import type { PasswordConfig } from "../../domain/value-objects/AuthConfig";
7
2
  import { getAuthPackage } from "../services/AuthPackage";
8
3
 
9
- export interface ValidationResult {
10
- isValid: boolean;
11
- error?: string; // This should be a localization key
12
- }
13
-
14
- export interface PasswordStrengthResult extends ValidationResult {
15
- requirements: PasswordRequirements;
16
- }
17
-
4
+ export interface ValidationResult { isValid: boolean; error?: string; }
5
+ export interface PasswordStrengthResult extends ValidationResult { requirements: PasswordRequirements; }
18
6
  export interface PasswordRequirements {
19
- hasMinLength: boolean;
20
- hasUppercase: boolean;
21
- hasLowercase: boolean;
22
- hasNumber: boolean;
23
- hasSpecialChar: boolean;
7
+ hasMinLength: boolean; hasUppercase: boolean; hasLowercase: boolean; hasNumber: boolean; hasSpecialChar: boolean;
24
8
  }
25
-
26
9
  export interface ValidationConfig {
27
- emailRegex: RegExp;
28
- uppercaseRegex: RegExp;
29
- lowercaseRegex: RegExp;
30
- numberRegex: RegExp;
31
- specialCharRegex: RegExp;
32
- displayNameMinLength: number;
10
+ emailRegex: RegExp; uppercaseRegex: RegExp; lowercaseRegex: RegExp;
11
+ numberRegex: RegExp; specialCharRegex: RegExp; displayNameMinLength: number;
33
12
  }
34
13
 
35
- const DEFAULT_VALIDATION_CONFIG: ValidationConfig = {
14
+ const DEFAULT_VAL_CONFIG: ValidationConfig = {
36
15
  emailRegex: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
37
16
  uppercaseRegex: /[A-Z]/,
38
17
  lowercaseRegex: /[a-z]/,
@@ -41,155 +20,57 @@ const DEFAULT_VALIDATION_CONFIG: ValidationConfig = {
41
20
  displayNameMinLength: 2,
42
21
  };
43
22
 
44
- function getValidationConfig(): ValidationConfig {
45
- const packageConfig = getAuthPackage()?.getConfig();
23
+ function getValConfig(): ValidationConfig {
24
+ const p = getAuthPackage()?.getConfig();
46
25
  return {
47
- emailRegex: packageConfig?.validation.emailRegex || DEFAULT_VALIDATION_CONFIG.emailRegex,
48
- uppercaseRegex: DEFAULT_VALIDATION_CONFIG.uppercaseRegex,
49
- lowercaseRegex: DEFAULT_VALIDATION_CONFIG.lowercaseRegex,
50
- numberRegex: DEFAULT_VALIDATION_CONFIG.numberRegex,
51
- specialCharRegex: DEFAULT_VALIDATION_CONFIG.specialCharRegex,
52
- displayNameMinLength: DEFAULT_VALIDATION_CONFIG.displayNameMinLength,
26
+ emailRegex: p?.validation.emailRegex || DEFAULT_VAL_CONFIG.emailRegex,
27
+ uppercaseRegex: DEFAULT_VAL_CONFIG.uppercaseRegex,
28
+ lowercaseRegex: DEFAULT_VAL_CONFIG.lowercaseRegex,
29
+ numberRegex: DEFAULT_VAL_CONFIG.numberRegex,
30
+ specialCharRegex: DEFAULT_VAL_CONFIG.specialCharRegex,
31
+ displayNameMinLength: DEFAULT_VAL_CONFIG.displayNameMinLength,
53
32
  };
54
33
  }
55
34
 
56
- /**
57
- * Validate email format
58
- */
59
35
  export function validateEmail(email: string): ValidationResult {
60
- if (!email || email.trim() === "") {
61
- return { isValid: false, error: "auth.validation.emailRequired" };
62
- }
63
-
64
- const config = getValidationConfig();
65
- if (!config.emailRegex.test(email.trim())) {
66
- return { isValid: false, error: "auth.validation.invalidEmail" };
67
- }
68
-
36
+ if (!email || email.trim() === "") return { isValid: false, error: "auth.validation.emailRequired" };
37
+ if (!getValConfig().emailRegex.test(email.trim())) return { isValid: false, error: "auth.validation.invalidEmail" };
69
38
  return { isValid: true };
70
39
  }
71
40
 
72
- /**
73
- * Validate password for login - only checks if password is provided
74
- * No strength requirements for login (existing users may have old passwords)
75
- */
76
41
  export function validatePasswordForLogin(password: string): ValidationResult {
77
- if (!password || password.length === 0) {
78
- return { isValid: false, error: "auth.validation.passwordRequired" };
79
- }
80
-
42
+ if (!password || password.length === 0) return { isValid: false, error: "auth.validation.passwordRequired" };
81
43
  return { isValid: true };
82
44
  }
83
45
 
84
- /**
85
- * Validate password strength for registration
86
- * Returns detailed requirements for UI feedback
87
- */
88
- export function validatePasswordForRegister(
89
- password: string,
90
- config: PasswordConfig
91
- ): PasswordStrengthResult {
92
- const validationConfig = getValidationConfig();
93
- const requirements: PasswordRequirements = {
46
+ export function validatePasswordForRegister(password: string, config: PasswordConfig): PasswordStrengthResult {
47
+ const v = getValConfig();
48
+ const req: PasswordRequirements = {
94
49
  hasMinLength: password.length >= config.minLength,
95
- hasUppercase: !config.requireUppercase || validationConfig.uppercaseRegex.test(password),
96
- hasLowercase: !config.requireLowercase || validationConfig.lowercaseRegex.test(password),
97
- hasNumber: !config.requireNumber || validationConfig.numberRegex.test(password),
98
- hasSpecialChar:
99
- !config.requireSpecialChar || validationConfig.specialCharRegex.test(password),
50
+ hasUppercase: !config.requireUppercase || v.uppercaseRegex.test(password),
51
+ hasLowercase: !config.requireLowercase || v.lowercaseRegex.test(password),
52
+ hasNumber: !config.requireNumber || v.numberRegex.test(password),
53
+ hasSpecialChar: !config.requireSpecialChar || v.specialCharRegex.test(password),
100
54
  };
101
55
 
102
- if (!password || password.length === 0) {
103
- return {
104
- isValid: false,
105
- error: "auth.validation.passwordRequired",
106
- requirements,
107
- };
108
- }
109
-
110
- if (!requirements.hasMinLength) {
111
- return {
112
- isValid: false,
113
- error: "auth.validation.passwordTooShort",
114
- requirements,
115
- };
116
- }
117
-
118
- if (config.requireUppercase && !validationConfig.uppercaseRegex.test(password)) {
119
- return {
120
- isValid: false,
121
- error: "auth.validation.passwordRequireUppercase",
122
- requirements,
123
- };
124
- }
56
+ if (!password) return { isValid: false, error: "auth.validation.passwordRequired", requirements: req };
57
+ if (!req.hasMinLength) return { isValid: false, error: "auth.validation.passwordTooShort", requirements: req };
58
+ if (config.requireUppercase && !req.hasUppercase) return { isValid: false, error: "auth.validation.passwordRequireUppercase", requirements: req };
59
+ if (config.requireLowercase && !req.hasLowercase) return { isValid: false, error: "auth.validation.passwordRequireLowercase", requirements: req };
60
+ if (config.requireNumber && !req.hasNumber) return { isValid: false, error: "auth.validation.passwordRequireNumber", requirements: req };
61
+ if (config.requireSpecialChar && !req.hasSpecialChar) return { isValid: false, error: "auth.validation.passwordRequireSpecialChar", requirements: req };
125
62
 
126
- if (config.requireLowercase && !validationConfig.lowercaseRegex.test(password)) {
127
- return {
128
- isValid: false,
129
- error: "auth.validation.passwordRequireLowercase",
130
- requirements,
131
- };
132
- }
133
-
134
- if (config.requireNumber && !validationConfig.numberRegex.test(password)) {
135
- return {
136
- isValid: false,
137
- error: "auth.validation.passwordRequireNumber",
138
- requirements,
139
- };
140
- }
141
-
142
- if (config.requireSpecialChar && !validationConfig.specialCharRegex.test(password)) {
143
- return {
144
- isValid: false,
145
- error: "auth.validation.passwordRequireSpecialChar",
146
- requirements,
147
- };
148
- }
149
-
150
- return { isValid: true, requirements };
63
+ return { isValid: true, requirements: req };
151
64
  }
152
65
 
153
- /**
154
- * Validate password confirmation
155
- */
156
- export function validatePasswordConfirmation(
157
- password: string,
158
- confirmPassword: string
159
- ): ValidationResult {
160
- if (!confirmPassword) {
161
- return { isValid: false, error: "auth.validation.confirmPasswordRequired" };
162
- }
163
-
164
- if (password !== confirmPassword) {
165
- return { isValid: false, error: "auth.validation.passwordsDoNotMatch" };
166
- }
167
-
66
+ export function validatePasswordConfirmation(password: string, confirm: string): ValidationResult {
67
+ if (!confirm) return { isValid: false, error: "auth.validation.confirmPasswordRequired" };
68
+ if (password !== confirm) return { isValid: false, error: "auth.validation.passwordsDoNotMatch" };
168
69
  return { isValid: true };
169
70
  }
170
71
 
171
- /**
172
- * Validate display name
173
- */
174
- export function validateDisplayName(
175
- displayName: string,
176
- minLength?: number
177
- ): ValidationResult {
178
- if (!displayName || displayName.trim() === "") {
179
- return { isValid: false, error: "auth.validation.nameRequired" };
180
- }
181
-
182
- const config = getValidationConfig();
183
- const actualMinLength = minLength ?? config.displayNameMinLength;
184
-
185
- if (displayName.trim().length < actualMinLength) {
186
- return {
187
- isValid: false,
188
- error: "auth.validation.nameTooShort",
189
- };
190
- }
191
-
72
+ export function validateDisplayName(name: string, minLength?: number): ValidationResult {
73
+ if (!name || name.trim() === "") return { isValid: false, error: "auth.validation.nameRequired" };
74
+ if (name.trim().length < (minLength ?? getValConfig().displayNameMinLength)) return { isValid: false, error: "auth.validation.nameTooShort" };
192
75
  return { isValid: true };
193
76
  }
194
-
195
-
@@ -1,247 +0,0 @@
1
- /**
2
- * AuthCoreService Tests
3
- */
4
-
5
- import { AuthCoreService } from '../../../src/infrastructure/services/AuthCoreService';
6
- import { DEFAULT_AUTH_CONFIG } from '../../../src/domain/value-objects/AuthConfig';
7
- import type { IAuthProvider } from '../../../src/application/ports/IAuthProvider';
8
- import type { AuthUser } from '../../../src/domain/entities/AuthUser';
9
-
10
- describe('AuthCoreService', () => {
11
- let authCoreService: AuthCoreService;
12
- let mockProvider: jest.Mocked<IAuthProvider>;
13
-
14
- beforeEach(() => {
15
- mockProvider = {
16
- initialize: jest.fn(),
17
- isInitialized: jest.fn().mockReturnValue(true),
18
- signIn: jest.fn(),
19
- signUp: jest.fn(),
20
- signOut: jest.fn(),
21
- getCurrentUser: jest.fn(),
22
- onAuthStateChange: jest.fn().mockReturnValue(jest.fn()),
23
- };
24
-
25
- authCoreService = new AuthCoreService(DEFAULT_AUTH_CONFIG);
26
- });
27
-
28
- describe('constructor', () => {
29
- it('should initialize with provided config', () => {
30
- const customConfig = {
31
- ...DEFAULT_AUTH_CONFIG,
32
- password: {
33
- ...DEFAULT_AUTH_CONFIG.password,
34
- minLength: 12,
35
- },
36
- };
37
-
38
- const service = new AuthCoreService(customConfig);
39
- expect(service.getConfig()).toEqual(customConfig);
40
- });
41
- });
42
-
43
- describe('initialize', () => {
44
- it('should initialize with IAuthProvider', async () => {
45
- await authCoreService.initialize(mockProvider);
46
- expect(mockProvider.initialize).toHaveBeenCalled();
47
- });
48
-
49
- it('should initialize with Firebase Auth instance', async () => {
50
- const mockFirebaseAuth = {
51
- currentUser: null,
52
- } as any;
53
-
54
- await expect(authCoreService.initialize(mockFirebaseAuth)).rejects.toThrow();
55
- });
56
-
57
- it('should throw error when no provider provided', async () => {
58
- await expect(authCoreService.initialize(null as any)).rejects.toThrow(
59
- 'Auth provider or Firebase Auth instance is required'
60
- );
61
- });
62
- });
63
-
64
- describe('isInitialized', () => {
65
- it('should return false when not initialized', () => {
66
- expect(authCoreService.isInitialized()).toBe(false);
67
- });
68
-
69
- it('should return true when initialized', async () => {
70
- await authCoreService.initialize(mockProvider);
71
- expect(authCoreService.isInitialized()).toBe(true);
72
- });
73
- });
74
-
75
- describe('signUp', () => {
76
- const mockUser: AuthUser = {
77
- uid: 'test-uid',
78
- email: 'test@example.com',
79
- displayName: 'Test User',
80
- isAnonymous: false,
81
- emailVerified: false,
82
- photoURL: null,
83
- };
84
-
85
- beforeEach(async () => {
86
- await authCoreService.initialize(mockProvider);
87
- });
88
-
89
- it('should sign up successfully with valid credentials', async () => {
90
- mockProvider.signUp.mockResolvedValue(mockUser);
91
-
92
- const result = await authCoreService.signUp({
93
- email: 'test@example.com',
94
- password: 'password123',
95
- displayName: 'Test User',
96
- });
97
-
98
- expect(result).toEqual(mockUser);
99
- expect(mockProvider.signUp).toHaveBeenCalledWith({
100
- email: 'test@example.com',
101
- password: 'password123',
102
- displayName: 'Test User',
103
- });
104
- });
105
-
106
- it('should sign up without display name', async () => {
107
- mockProvider.signUp.mockResolvedValue(mockUser);
108
-
109
- await authCoreService.signUp({
110
- email: 'test@example.com',
111
- password: 'password123',
112
- });
113
-
114
- expect(mockProvider.signUp).toHaveBeenCalledWith({
115
- email: 'test@example.com',
116
- password: 'password123',
117
- displayName: undefined,
118
- });
119
- });
120
-
121
- it('should throw error when not initialized', async () => {
122
- const uninitializedService = new AuthCoreService(DEFAULT_AUTH_CONFIG);
123
-
124
- await expect(uninitializedService.signUp({
125
- email: 'test@example.com',
126
- password: 'password123',
127
- })).rejects.toThrow('Auth service is not initialized');
128
- });
129
- });
130
-
131
- describe('signIn', () => {
132
- const mockUser: AuthUser = {
133
- uid: 'test-uid',
134
- email: 'test@example.com',
135
- displayName: 'Test User',
136
- isAnonymous: false,
137
- emailVerified: false,
138
- photoURL: null,
139
- };
140
-
141
- beforeEach(async () => {
142
- await authCoreService.initialize(mockProvider);
143
- });
144
-
145
- it('should sign in successfully with valid credentials', async () => {
146
- mockProvider.signIn.mockResolvedValue(mockUser);
147
-
148
- const result = await authCoreService.signIn({
149
- email: 'test@example.com',
150
- password: 'password123',
151
- });
152
-
153
- expect(result).toEqual(mockUser);
154
- expect(mockProvider.signIn).toHaveBeenCalledWith({
155
- email: 'test@example.com',
156
- password: 'password123',
157
- });
158
- });
159
-
160
- it('should throw error when not initialized', async () => {
161
- const uninitializedService = new AuthCoreService(DEFAULT_AUTH_CONFIG);
162
-
163
- await expect(uninitializedService.signIn({
164
- email: 'test@example.com',
165
- password: 'password123',
166
- })).rejects.toThrow('Auth service is not initialized');
167
- });
168
- });
169
-
170
- describe('signOut', () => {
171
- beforeEach(async () => {
172
- await authCoreService.initialize(mockProvider);
173
- });
174
-
175
- it('should sign out successfully', async () => {
176
- await authCoreService.signOut();
177
- expect(mockProvider.signOut).toHaveBeenCalled();
178
- });
179
-
180
- it('should handle sign out when not initialized', async () => {
181
- const uninitializedService = new AuthCoreService(DEFAULT_AUTH_CONFIG);
182
-
183
- await expect(uninitializedService.signOut()).resolves.not.toThrow();
184
- });
185
- });
186
-
187
- describe('getCurrentUser', () => {
188
- const mockUser: AuthUser = {
189
- uid: 'test-uid',
190
- email: 'test@example.com',
191
- displayName: 'Test User',
192
- isAnonymous: false,
193
- emailVerified: false,
194
- photoURL: null,
195
- };
196
-
197
- it('should return null when not initialized', () => {
198
- const result = authCoreService.getCurrentUser();
199
- expect(result).toBeNull();
200
- });
201
-
202
- it('should return current user when initialized', async () => {
203
- mockProvider.getCurrentUser.mockReturnValue(mockUser);
204
- await authCoreService.initialize(mockProvider);
205
-
206
- const result = authCoreService.getCurrentUser();
207
- expect(result).toEqual(mockUser);
208
- });
209
-
210
- it('should return null when no current user', async () => {
211
- mockProvider.getCurrentUser.mockReturnValue(null);
212
- await authCoreService.initialize(mockProvider);
213
-
214
- const result = authCoreService.getCurrentUser();
215
- expect(result).toBeNull();
216
- });
217
- });
218
-
219
- describe('onAuthStateChange', () => {
220
- it('should return cleanup function when not initialized', () => {
221
- const callback = jest.fn();
222
- const cleanup = authCoreService.onAuthStateChange(callback);
223
-
224
- expect(callback).toHaveBeenCalledWith(null);
225
- expect(typeof cleanup).toBe('function');
226
- });
227
-
228
- it('should subscribe to auth state changes when initialized', async () => {
229
- const callback = jest.fn();
230
- const mockCleanup = jest.fn();
231
- mockProvider.onAuthStateChange.mockReturnValue(mockCleanup);
232
-
233
- await authCoreService.initialize(mockProvider);
234
- const cleanup = authCoreService.onAuthStateChange(callback);
235
-
236
- expect(mockProvider.onAuthStateChange).toHaveBeenCalledWith(callback);
237
- expect(cleanup).toBe(mockCleanup);
238
- });
239
- });
240
-
241
- describe('getConfig', () => {
242
- it('should return the current config', () => {
243
- const config = authCoreService.getConfig();
244
- expect(config).toEqual(DEFAULT_AUTH_CONFIG);
245
- });
246
- });
247
- });