@umituz/react-native-auth 3.4.32 → 3.4.34
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/README.md +347 -348
- package/package.json +2 -3
- package/src/application/README.md +323 -442
- package/src/domain/ConfigAndErrors.md +296 -431
- package/src/domain/README.md +361 -210
- package/src/domain/entities/AuthUser.md +231 -372
- package/src/domain/entities/UserProfile.md +271 -441
- package/src/index.ts +35 -0
- package/src/infrastructure/README.md +388 -444
- package/src/infrastructure/services/README.md +386 -312
- package/src/infrastructure/utils/validation/BaseValidators.ts +35 -0
- package/src/infrastructure/utils/validation/CollectionValidators.ts +56 -0
- package/src/infrastructure/utils/validation/DateValidators.ts +63 -0
- package/src/infrastructure/utils/validation/FormValidators.ts +22 -0
- package/src/infrastructure/utils/validation/NumberValidators.ts +55 -0
- package/src/infrastructure/utils/validation/StringValidators.ts +55 -0
- package/src/infrastructure/utils/validation/sanitization.ts +98 -0
- package/src/infrastructure/utils/validation/types.ts +15 -0
- package/src/presentation/README.md +631 -563
- package/src/presentation/components/ProfileComponents.md +307 -504
- package/src/presentation/components/README.md +254 -92
- package/src/presentation/hooks/README.md +247 -83
- package/src/presentation/hooks/useAccountManagement.md +295 -344
- package/src/presentation/hooks/useAuth.md +271 -227
- package/src/presentation/hooks/useAuthBottomSheet.md +417 -367
- package/src/presentation/hooks/useAuthRequired.md +308 -194
- package/src/presentation/hooks/useProfileUpdate.md +251 -279
- package/src/presentation/hooks/useSocialLogin.md +312 -287
- package/src/presentation/hooks/useUserProfile.md +259 -192
- package/src/presentation/screens/README.md +151 -153
|
@@ -6,322 +6,294 @@ Hooks for profile update operations and profile editing form management.
|
|
|
6
6
|
|
|
7
7
|
## useProfileUpdate
|
|
8
8
|
|
|
9
|
-
Hook for
|
|
9
|
+
Hook for updating user profile information (display name, photo URL).
|
|
10
10
|
|
|
11
|
-
###
|
|
11
|
+
### Strategy
|
|
12
12
|
|
|
13
|
+
**Purpose**: Provides functionality to update user profile data in Firebase Auth and Firestore. Implementation provided by app using Firebase SDK.
|
|
14
|
+
|
|
15
|
+
**When to Use**:
|
|
16
|
+
- User profile editing screens
|
|
17
|
+
- Settings screens with profile updates
|
|
18
|
+
- Need to update display name or photo
|
|
19
|
+
- Profile modification operations
|
|
20
|
+
|
|
21
|
+
**Import Path**:
|
|
13
22
|
```typescript
|
|
14
23
|
import { useProfileUpdate } from '@umituz/react-native-auth';
|
|
24
|
+
```
|
|
15
25
|
|
|
16
|
-
|
|
17
|
-
|
|
26
|
+
**Hook Location**: `src/presentation/hooks/useProfileUpdate.ts`
|
|
27
|
+
|
|
28
|
+
### Rules
|
|
29
|
+
|
|
30
|
+
**MUST**:
|
|
31
|
+
- Validate user is authenticated before updating
|
|
32
|
+
- Validate input data before calling update
|
|
33
|
+
- Handle loading state during update
|
|
34
|
+
- Display error messages on failure
|
|
35
|
+
- Update both Firebase Auth and Firestore
|
|
36
|
+
- Handle anonymous users appropriately
|
|
37
|
+
|
|
38
|
+
**MUST NOT**:
|
|
39
|
+
- Allow anonymous users to update profile
|
|
40
|
+
- Update profile without validation
|
|
41
|
+
- Expose sensitive error details
|
|
42
|
+
- Allow partial updates (all-or-nothing)
|
|
43
|
+
|
|
44
|
+
### Constraints
|
|
45
|
+
|
|
46
|
+
**PARAMETERS**:
|
|
47
|
+
- `displayName?: string` - New display name
|
|
48
|
+
- `photoURL?: string` - New profile photo URL
|
|
49
|
+
|
|
50
|
+
**OPERATION RULES**:
|
|
51
|
+
- Updates Firebase Auth user profile
|
|
52
|
+
- Updates Firestore user document
|
|
53
|
+
- Transactional (both or none)
|
|
54
|
+
- Auto-updates auth state
|
|
55
|
+
- Triggers profile listeners
|
|
56
|
+
|
|
57
|
+
**LIMITATIONS**:
|
|
58
|
+
- Cannot update email (use separate method)
|
|
59
|
+
- Cannot update password (use separate method)
|
|
60
|
+
- Anonymous users cannot update
|
|
61
|
+
- Requires authentication
|
|
62
|
+
|
|
63
|
+
**ERROR HANDLING**:
|
|
64
|
+
- Validation errors before API call
|
|
65
|
+
- Network errors during update
|
|
66
|
+
- Permission errors (user not authenticated)
|
|
67
|
+
- Firebase errors
|
|
18
68
|
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
await updateProfile(data);
|
|
22
|
-
} catch (err) {
|
|
23
|
-
console.error(err);
|
|
24
|
-
}
|
|
25
|
-
};
|
|
69
|
+
---
|
|
26
70
|
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
```
|
|
71
|
+
## useProfileEdit
|
|
30
72
|
|
|
31
|
-
|
|
73
|
+
Hook for managing profile editing form state and validation.
|
|
32
74
|
|
|
33
|
-
|
|
34
|
-
|------|------|-------------|
|
|
35
|
-
| `updateProfile` | `(params: UpdateProfileParams) => Promise<void>` | Profile update function |
|
|
36
|
-
| `isUpdating` | `boolean` | Update in progress |
|
|
37
|
-
| `error` | `string \| null` | Error message |
|
|
75
|
+
### Strategy
|
|
38
76
|
|
|
39
|
-
|
|
77
|
+
**Purpose**: Provides form state management for profile editing with validation and change tracking.
|
|
40
78
|
|
|
79
|
+
**When to Use**:
|
|
80
|
+
- Profile editing forms
|
|
81
|
+
- Settings screens with profile edits
|
|
82
|
+
- Need form validation for profile data
|
|
83
|
+
- Want to track form modifications
|
|
84
|
+
|
|
85
|
+
**Import Path**:
|
|
41
86
|
```typescript
|
|
42
|
-
|
|
43
|
-
const { user } = useAuth();
|
|
44
|
-
const [isUpdating, setIsUpdating] = useState(false);
|
|
45
|
-
const [error, setError] = useState<string | null>(null);
|
|
46
|
-
|
|
47
|
-
const updateProfile = async (params: UpdateProfileParams) => {
|
|
48
|
-
if (!user) {
|
|
49
|
-
throw new Error("No user logged in");
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (user.isAnonymous) {
|
|
53
|
-
throw new Error("Anonymous users cannot update profile");
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
setIsUpdating(true);
|
|
57
|
-
setError(null);
|
|
58
|
-
|
|
59
|
-
try {
|
|
60
|
-
// Update profile in Firebase Auth
|
|
61
|
-
await updateProfile(user, {
|
|
62
|
-
displayName: params.displayName,
|
|
63
|
-
photoURL: params.photoURL,
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// Update user document in Firestore
|
|
67
|
-
await updateDoc(doc(db, 'users', user.uid), {
|
|
68
|
-
displayName: params.displayName,
|
|
69
|
-
photoURL: params.photoURL,
|
|
70
|
-
updatedAt: serverTimestamp(),
|
|
71
|
-
});
|
|
72
|
-
} catch (err) {
|
|
73
|
-
const message = err instanceof Error ? err.message : 'Update failed';
|
|
74
|
-
setError(message);
|
|
75
|
-
throw err;
|
|
76
|
-
} finally {
|
|
77
|
-
setIsUpdating(false);
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
return { updateProfile, isUpdating, error };
|
|
82
|
-
}
|
|
87
|
+
import { useProfileEdit } from '@umituz/react-native-auth';
|
|
83
88
|
```
|
|
84
89
|
|
|
90
|
+
**Hook Location**: `src/presentation/hooks/useProfileUpdate.ts`
|
|
91
|
+
|
|
92
|
+
### Rules
|
|
93
|
+
|
|
94
|
+
**MUST**:
|
|
95
|
+
- Validate form before submission
|
|
96
|
+
- Show validation errors to user
|
|
97
|
+
- Track form modifications
|
|
98
|
+
- Handle email field as read-only
|
|
99
|
+
- Provide clear error messages
|
|
100
|
+
- Reset form after successful submission
|
|
101
|
+
|
|
102
|
+
**MUST NOT**:
|
|
103
|
+
- Allow invalid form submission
|
|
104
|
+
- Allow email modification (read-only)
|
|
105
|
+
- Submit unchanged data
|
|
106
|
+
- Clear form without confirmation if modified
|
|
107
|
+
|
|
108
|
+
### Constraints
|
|
109
|
+
|
|
110
|
+
**FORM FIELDS**:
|
|
111
|
+
- `displayName: string` - Editable
|
|
112
|
+
- `email: string` - Read-only
|
|
113
|
+
- `photoURL: string | null` - Editable
|
|
114
|
+
- `isModified: boolean` - Auto-calculated
|
|
115
|
+
|
|
116
|
+
**VALIDATION RULES**:
|
|
117
|
+
- Display name: Cannot be empty
|
|
118
|
+
- Email: Valid format (if provided)
|
|
119
|
+
- Photo URL: Valid URL format (if provided)
|
|
120
|
+
|
|
121
|
+
**RETURNED FUNCTIONS**:
|
|
122
|
+
- `setDisplayName: (value: string) => void`
|
|
123
|
+
- `setEmail: (value: string) => void`
|
|
124
|
+
- `setPhotoURL: (value: string | null) => void`
|
|
125
|
+
- `resetForm: (initial: Partial<ProfileEditFormState>) => void`
|
|
126
|
+
- `validateForm: () => { isValid: boolean; errors: string[] }`
|
|
127
|
+
|
|
128
|
+
**CHANGE TRACKING**:
|
|
129
|
+
- `isModified` automatically calculated
|
|
130
|
+
- Compares current vs initial values
|
|
131
|
+
- Triggers re-calculation on any change
|
|
132
|
+
- Used to enable/disable save button
|
|
133
|
+
|
|
85
134
|
---
|
|
86
135
|
|
|
87
|
-
##
|
|
136
|
+
## Validation Strategy
|
|
88
137
|
|
|
89
|
-
|
|
138
|
+
### Strategy
|
|
90
139
|
|
|
91
|
-
|
|
140
|
+
**Purpose**: Ensure profile data meets requirements before submission.
|
|
92
141
|
|
|
93
|
-
|
|
94
|
-
|
|
142
|
+
**Rules**:
|
|
143
|
+
- MUST validate all fields before submission
|
|
144
|
+
- MUST show clear error messages
|
|
145
|
+
- MUST prevent invalid submissions
|
|
146
|
+
- MUST provide real-time validation feedback
|
|
95
147
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
setPhotoURL,
|
|
102
|
-
resetForm,
|
|
103
|
-
validateForm,
|
|
104
|
-
} = useProfileEdit({
|
|
105
|
-
displayName: user?.displayName || '',
|
|
106
|
-
email: user?.email || '',
|
|
107
|
-
photoURL: user?.photoURL || null,
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
const handleSave = () => {
|
|
111
|
-
const { isValid, errors } = validateForm();
|
|
112
|
-
|
|
113
|
-
if (!isValid) {
|
|
114
|
-
Alert.alert('Error', errors.join('\n'));
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
updateProfile({
|
|
119
|
-
displayName: formState.displayName,
|
|
120
|
-
photoURL: formState.photoURL,
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
navigation.goBack();
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
return (
|
|
127
|
-
<ScrollView>
|
|
128
|
-
<TextInput
|
|
129
|
-
value={formState.displayName}
|
|
130
|
-
onChangeText={setDisplayName}
|
|
131
|
-
placeholder="Full Name"
|
|
132
|
-
/>
|
|
133
|
-
|
|
134
|
-
<TextInput
|
|
135
|
-
value={formState.email}
|
|
136
|
-
onChangeText={setEmail}
|
|
137
|
-
placeholder="Email"
|
|
138
|
-
editable={false}
|
|
139
|
-
/>
|
|
140
|
-
|
|
141
|
-
<AvatarUploader
|
|
142
|
-
photoURL={formState.photoURL}
|
|
143
|
-
onImageSelected={setPhotoURL}
|
|
144
|
-
/>
|
|
145
|
-
|
|
146
|
-
<View style={styles.buttons}>
|
|
147
|
-
<Button onPress={navigation.goBack}>Cancel</Button>
|
|
148
|
-
<Button
|
|
149
|
-
onPress={handleSave}
|
|
150
|
-
disabled={!formState.isModified}
|
|
151
|
-
>
|
|
152
|
-
Save
|
|
153
|
-
</Button>
|
|
154
|
-
</View>
|
|
155
|
-
</ScrollView>
|
|
156
|
-
);
|
|
157
|
-
}
|
|
158
|
-
```
|
|
148
|
+
**MUST NOT**:
|
|
149
|
+
- Allow empty display names
|
|
150
|
+
- Accept invalid email formats
|
|
151
|
+
- Submit with validation errors
|
|
152
|
+
- Hide validation errors
|
|
159
153
|
|
|
160
|
-
###
|
|
154
|
+
### Constraints
|
|
161
155
|
|
|
162
|
-
|
|
156
|
+
**DISPLAY NAME VALIDATION**:
|
|
157
|
+
- Required field
|
|
158
|
+
- Minimum length: 1 character
|
|
159
|
+
- Maximum length: 100 characters
|
|
160
|
+
- No special character restrictions
|
|
163
161
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
| `setPhotoURL` | `(value: string \| null) => void` | Set photo URL |
|
|
170
|
-
| `resetForm` | `(initial: Partial<ProfileEditFormState>) => void` | Reset form |
|
|
171
|
-
| `validateForm` | `() => { isValid: boolean; errors: string[] }` | Validate form |
|
|
162
|
+
**EMAIL VALIDATION**:
|
|
163
|
+
- Valid email format required
|
|
164
|
+
- Read-only field (cannot change)
|
|
165
|
+
- Must match Firebase user email
|
|
166
|
+
- Used for display only
|
|
172
167
|
|
|
173
|
-
|
|
168
|
+
**PHOTO URL VALIDATION**:
|
|
169
|
+
- Optional field
|
|
170
|
+
- Must be valid URL if provided
|
|
171
|
+
- Supports HTTP, HTTPS URLs
|
|
172
|
+
- Can be cleared (set to null)
|
|
174
173
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
| `isModified` | `boolean` | Form has been modified |
|
|
174
|
+
**VALIDATION TIMING**:
|
|
175
|
+
- Real-time validation on input
|
|
176
|
+
- Final validation on submit
|
|
177
|
+
- Clear errors on correction
|
|
178
|
+
- Error messages localized
|
|
181
179
|
|
|
182
|
-
|
|
180
|
+
---
|
|
183
181
|
|
|
184
|
-
|
|
182
|
+
## Anonymous User Handling
|
|
185
183
|
|
|
186
|
-
|
|
187
|
-
- **Email**: Valid email format (if provided)
|
|
184
|
+
### Strategy
|
|
188
185
|
|
|
189
|
-
|
|
190
|
-
const { isValid, errors } = validateForm();
|
|
186
|
+
**Purpose**: Prevent profile updates from anonymous users.
|
|
191
187
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
188
|
+
**Rules**:
|
|
189
|
+
- MUST check user is not anonymous
|
|
190
|
+
- MUST hide profile edit for anonymous users
|
|
191
|
+
- MUST show upgrade prompt instead
|
|
192
|
+
- MUST NOT allow anonymous profile updates
|
|
197
193
|
|
|
198
|
-
|
|
194
|
+
**Constraints**:
|
|
195
|
+
- Anonymous users cannot update profile
|
|
196
|
+
- Show "Create account" prompt
|
|
197
|
+
- Guide to registration
|
|
198
|
+
- Preserve anonymous data during upgrade
|
|
199
199
|
|
|
200
|
-
|
|
200
|
+
---
|
|
201
201
|
|
|
202
|
-
|
|
203
|
-
function ProfilePhotoSection() {
|
|
204
|
-
const { formState, setPhotoURL } = useProfileEdit(initialState);
|
|
205
|
-
|
|
206
|
-
const handlePickImage = async () => {
|
|
207
|
-
const result = await launchImageLibrary({
|
|
208
|
-
mediaType: 'photo',
|
|
209
|
-
quality: 0.8,
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
if (result.assets?.[0]) {
|
|
213
|
-
// Upload to storage and get URL
|
|
214
|
-
const url = await uploadToStorage(result.assets[0].uri);
|
|
215
|
-
setPhotoURL(url);
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
return (
|
|
220
|
-
<TouchableOpacity onPress={handlePickImage}>
|
|
221
|
-
{formState.photoURL ? (
|
|
222
|
-
<Image source={{ uri: formState.photoURL }} />
|
|
223
|
-
) : (
|
|
224
|
-
<View style={styles.placeholder}>
|
|
225
|
-
<Text>Select Photo</Text>
|
|
226
|
-
</View>
|
|
227
|
-
)}
|
|
228
|
-
</TouchableOpacity>
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
```
|
|
202
|
+
## Error Handling
|
|
232
203
|
|
|
233
|
-
###
|
|
204
|
+
### Strategy
|
|
234
205
|
|
|
235
|
-
|
|
236
|
-
function EditProfileScreen({ navigation }) {
|
|
237
|
-
const {
|
|
238
|
-
formState,
|
|
239
|
-
resetForm,
|
|
240
|
-
validateForm
|
|
241
|
-
} = useProfileEdit(initialState);
|
|
242
|
-
|
|
243
|
-
useEffect(() => {
|
|
244
|
-
const unsubscribe = navigation.addListener('beforeRemove', (e) => {
|
|
245
|
-
if (!formState.isModified) {
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
e.preventDefault();
|
|
250
|
-
|
|
251
|
-
Alert.alert(
|
|
252
|
-
'Unsaved Changes',
|
|
253
|
-
'You have unsaved changes. What would you like to do?',
|
|
254
|
-
[
|
|
255
|
-
{ text: 'Don\'t Save', style: 'cancel' },
|
|
256
|
-
{
|
|
257
|
-
text: 'Save',
|
|
258
|
-
onPress: () => {
|
|
259
|
-
saveChanges();
|
|
260
|
-
navigation.dispatch(e.data.action);
|
|
261
|
-
}
|
|
262
|
-
},
|
|
263
|
-
{
|
|
264
|
-
text: 'Discard',
|
|
265
|
-
style: 'destructive',
|
|
266
|
-
onPress: () => {
|
|
267
|
-
resetForm(initialState);
|
|
268
|
-
navigation.dispatch(e.data.action);
|
|
269
|
-
}
|
|
270
|
-
},
|
|
271
|
-
]
|
|
272
|
-
);
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
return unsubscribe;
|
|
276
|
-
}, [navigation, formState.isModified]);
|
|
277
|
-
|
|
278
|
-
// ...
|
|
279
|
-
}
|
|
280
|
-
```
|
|
206
|
+
**Purpose**: Graceful handling of profile update failures.
|
|
281
207
|
|
|
282
|
-
|
|
208
|
+
**Rules**:
|
|
209
|
+
- MUST catch all errors during update
|
|
210
|
+
- MUST show user-friendly error messages
|
|
211
|
+
- MUST allow retry after failures
|
|
212
|
+
- MUST not lose form data on error
|
|
283
213
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
214
|
+
**MUST NOT**:
|
|
215
|
+
- Show raw error messages
|
|
216
|
+
- Crash on update failures
|
|
217
|
+
- Lose user input on errors
|
|
218
|
+
- Block retry attempts
|
|
219
|
+
|
|
220
|
+
### Constraints
|
|
221
|
+
|
|
222
|
+
**ERROR TYPES**:
|
|
223
|
+
- Validation errors: Before API call
|
|
224
|
+
- Network errors: During update
|
|
225
|
+
- Permission errors: Not authenticated
|
|
226
|
+
- Firebase errors: From service
|
|
227
|
+
|
|
228
|
+
**ERROR RECOVERY**:
|
|
229
|
+
- Keep form data on error
|
|
230
|
+
- Allow user to retry
|
|
231
|
+
- Clear errors on new input
|
|
232
|
+
- Show retry button
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Performance Optimization
|
|
237
|
+
|
|
238
|
+
### Strategy
|
|
239
|
+
|
|
240
|
+
**Purpose**: Efficient form state management and updates.
|
|
241
|
+
|
|
242
|
+
**Rules**:
|
|
243
|
+
- MUST minimize unnecessary re-renders
|
|
244
|
+
- MUST debounce validation if expensive
|
|
245
|
+
- MUST optimize form state updates
|
|
246
|
+
- MUST prevent excessive recalculations
|
|
247
|
+
|
|
248
|
+
**Constraints**:
|
|
249
|
+
- Form state in local component
|
|
250
|
+
- Efficient validation checks
|
|
251
|
+
- Minimal prop drilling
|
|
252
|
+
- Optimized re-render triggers
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Security Considerations
|
|
257
|
+
|
|
258
|
+
### Strategy
|
|
259
|
+
|
|
260
|
+
**Purpose**: Secure profile data updates.
|
|
261
|
+
|
|
262
|
+
**Rules**:
|
|
263
|
+
- MUST validate user owns profile
|
|
264
|
+
- MUST sanitize input data
|
|
265
|
+
- MUST use secure upload for photos
|
|
266
|
+
- MUST not expose sensitive data
|
|
267
|
+
|
|
268
|
+
**MUST NOT**:
|
|
269
|
+
- Allow cross-user profile updates
|
|
270
|
+
- Accept unvalidated photo URLs
|
|
271
|
+
- Expose user IDs in errors
|
|
272
|
+
- Log profile data with sensitive info
|
|
273
|
+
|
|
274
|
+
### Constraints
|
|
275
|
+
|
|
276
|
+
**PERMISSION CHECKS**:
|
|
277
|
+
- User can only update own profile
|
|
278
|
+
- Firebase security rules enforce
|
|
279
|
+
- Server-side validation required
|
|
280
|
+
- Token-based authentication
|
|
281
|
+
|
|
282
|
+
**DATA SANITIZATION**:
|
|
283
|
+
- Trim whitespace from names
|
|
284
|
+
- Validate URL formats
|
|
285
|
+
- Escape special characters
|
|
286
|
+
- Prevent XSS attacks
|
|
287
|
+
|
|
288
|
+
---
|
|
322
289
|
|
|
323
290
|
## Related Hooks
|
|
324
291
|
|
|
325
|
-
-
|
|
326
|
-
-
|
|
327
|
-
-
|
|
292
|
+
- **`useAuth`** (`src/presentation/hooks/useAuth.ts`) - Authentication state
|
|
293
|
+
- **`useUserProfile`** (`src/presentation/hooks/useUserProfile.ts`) - Profile display data
|
|
294
|
+
- **`useAccountManagement`** (`src/presentation/hooks/useAccountManagement.md`) - Account operations
|
|
295
|
+
|
|
296
|
+
## Related Components
|
|
297
|
+
|
|
298
|
+
- **`ProfileSection`** (`src/presentation/components/ProfileComponents.md`) - Profile display
|
|
299
|
+
- **`EditProfileForm`** (`src/presentation/components/ProfileComponents.md`) - Profile editing UI
|