@@ -74,9 +74,9 @@ class AuthService {
74
74
/// Throws [OperationFailedException] for user lookup/creation or token errors.
75
75
Future <({User user, String token})> completeEmailSignIn (
76
76
String email,
77
- String code,
78
- // User? currentAuthUser, // Parameter for potential future linking logic
79
- ) async {
77
+ String code, {
78
+ User ? currentAuthUser, // Parameter for potential future linking logic
79
+ } ) async {
80
80
// 1. Validate the code for standard sign-in
81
81
final isValidCode = await _verificationCodeStorageService
82
82
.validateSignInCode (email, code);
@@ -96,53 +96,139 @@ class AuthService {
96
96
);
97
97
}
98
98
99
- // 2. Find or create the user
99
+ // 2. Find or create the user, and migrate data if anonymous
100
100
User user;
101
101
try {
102
- // Attempt to find user by email (assuming a query method exists)
103
- // NOTE: HtDataRepository<User> currently lacks findByEmail.
104
- // We'll simulate this by querying all and filtering for now.
105
- // Replace with a proper query when available.
106
- final query = {'email' : email}; // Hypothetical query
107
- final paginatedResponse = await _userRepository.readAllByQuery (query);
108
-
109
- if (paginatedResponse.items.isNotEmpty) {
110
- user = paginatedResponse.items.first;
111
- print ('Found existing user: ${user .id } for email $email ' );
112
- } else {
113
- // User not found, create a new one
114
- print ('User not found for $email , creating new user.' );
115
- user = User (
116
- id: _uuid.v4 (), // Generate new ID
117
- email: email,
118
- role: UserRole .standardUser, // Email verified user is standard user
119
- );
120
- user = await _userRepository.create (item: user); // Save the new user
121
- print ('Created new user: ${user .id }' );
122
-
123
- // Create default UserAppSettings for the new user
124
- final defaultAppSettings = UserAppSettings (id: user.id);
125
- await _userAppSettingsRepository.create (
126
- item: defaultAppSettings,
127
- userId: user.id, // Pass user ID for scoping
102
+ if (currentAuthUser != null &&
103
+ currentAuthUser.role == UserRole .guestUser) {
104
+ // This is an anonymous user linking their account.
105
+ // Migrate their existing data to the new permanent user.
106
+ print (
107
+ 'Anonymous user ${currentAuthUser .id } is linking email $email . '
108
+ 'Migrating data...' ,
128
109
);
129
- print ('Created default UserAppSettings for user: ${user .id }' );
130
110
131
- // Create default UserContentPreferences for the new user
132
- final defaultUserPreferences = UserContentPreferences (id: user.id);
133
- await _userContentPreferencesRepository.create (
134
- item: defaultUserPreferences,
135
- userId: user.id, // Pass user ID for scoping
111
+ // Fetch existing settings and preferences for the anonymous user
112
+ UserAppSettings ? existingAppSettings;
113
+ UserContentPreferences ? existingUserPreferences;
114
+ try {
115
+ existingAppSettings = await _userAppSettingsRepository.read (
116
+ id: currentAuthUser.id,
117
+ userId: currentAuthUser.id,
118
+ );
119
+ existingUserPreferences = await _userContentPreferencesRepository.read (
120
+ id: currentAuthUser.id,
121
+ userId: currentAuthUser.id,
122
+ );
123
+ print (
124
+ 'Fetched existing settings and preferences for anonymous user '
125
+ '${currentAuthUser .id }.' ,
126
+ );
127
+ } on NotFoundException {
128
+ print (
129
+ 'No existing settings/preferences found for anonymous user '
130
+ '${currentAuthUser .id }. Creating new ones.' ,
131
+ );
132
+ // If not found, proceed to create new ones later.
133
+ } catch (e) {
134
+ print (
135
+ 'Error fetching existing settings/preferences for anonymous user '
136
+ '${currentAuthUser .id }: $e ' ,
137
+ );
138
+ // Log and continue, new defaults will be created.
139
+ }
140
+
141
+ // Update the existing anonymous user to be permanent
142
+ user = currentAuthUser.copyWith (
143
+ email: email,
144
+ role: UserRole .standardUser,
136
145
);
137
- print ('Created default UserContentPreferences for user: ${user .id }' );
146
+ user = await _userRepository.update (id: user.id, item: user);
147
+ print ('Updated anonymous user ${user .id } to permanent with email $email .' );
148
+
149
+ // Update or create UserAppSettings for the now-permanent user
150
+ if (existingAppSettings != null ) {
151
+ // Update existing settings with the new user ID (though it's the same)
152
+ // and persist.
153
+ await _userAppSettingsRepository.update (
154
+ id: existingAppSettings.id,
155
+ item: existingAppSettings.copyWith (id: user.id),
156
+ userId: user.id,
157
+ );
158
+ print ('Migrated UserAppSettings for user: ${user .id }' );
159
+ } else {
160
+ // Create default settings if none existed for the anonymous user
161
+ final defaultAppSettings = UserAppSettings (id: user.id);
162
+ await _userAppSettingsRepository.create (
163
+ item: defaultAppSettings,
164
+ userId: user.id,
165
+ );
166
+ print ('Created default UserAppSettings for user: ${user .id }' );
167
+ }
168
+
169
+ // Update or create UserContentPreferences for the now-permanent user
170
+ if (existingUserPreferences != null ) {
171
+ // Update existing preferences with the new user ID (though it's the same)
172
+ // and persist.
173
+ await _userContentPreferencesRepository.update (
174
+ id: existingUserPreferences.id,
175
+ item: existingUserPreferences.copyWith (id: user.id),
176
+ userId: user.id,
177
+ );
178
+ print ('Migrated UserContentPreferences for user: ${user .id }' );
179
+ } else {
180
+ // Create default preferences if none existed for the anonymous user
181
+ final defaultUserPreferences = UserContentPreferences (id: user.id);
182
+ await _userContentPreferencesRepository.create (
183
+ item: defaultUserPreferences,
184
+ userId: user.id,
185
+ );
186
+ print ('Created default UserContentPreferences for user: ${user .id }' );
187
+ }
188
+ } else {
189
+ // Standard sign-in/sign-up flow (not anonymous linking)
190
+ // Attempt to find user by email
191
+ final query = {'email' : email};
192
+ final paginatedResponse = await _userRepository.readAllByQuery (query);
193
+
194
+ if (paginatedResponse.items.isNotEmpty) {
195
+ user = paginatedResponse.items.first;
196
+ print ('Found existing user: ${user .id } for email $email ' );
197
+ } else {
198
+ // User not found, create a new one
199
+ print ('User not found for $email , creating new user.' );
200
+ user = User (
201
+ id: _uuid.v4 (), // Generate new ID
202
+ email: email,
203
+ role: UserRole .standardUser, // Email verified user is standard user
204
+ );
205
+ user = await _userRepository.create (item: user); // Save the new user
206
+ print ('Created new user: ${user .id }' );
207
+
208
+ // Create default UserAppSettings for the new user
209
+ final defaultAppSettings = UserAppSettings (id: user.id);
210
+ await _userAppSettingsRepository.create (
211
+ item: defaultAppSettings,
212
+ userId: user.id, // Pass user ID for scoping
213
+ );
214
+ print ('Created default UserAppSettings for user: ${user .id }' );
215
+
216
+ // Create default UserContentPreferences for the new user
217
+ final defaultUserPreferences = UserContentPreferences (id: user.id);
218
+ await _userContentPreferencesRepository.create (
219
+ item: defaultUserPreferences,
220
+ userId: user.id, // Pass user ID for scoping
221
+ );
222
+ print ('Created default UserContentPreferences for user: ${user .id }' );
223
+ }
138
224
}
139
225
} on HtHttpException catch (e) {
140
- print ('Error finding/creating user for $email : $e ' );
226
+ print ('Error finding/creating/migrating user for $email : $e ' );
141
227
throw const OperationFailedException (
142
- 'Failed to find or create user account.' ,
228
+ 'Failed to find, create, or migrate user account.' ,
143
229
);
144
230
} catch (e) {
145
- print ('Unexpected error during user lookup/creation for $email : $e ' );
231
+ print ('Unexpected error during user lookup/creation/migration for $email : $e ' );
146
232
throw const OperationFailedException ('Failed to process user account.' );
147
233
}
148
234
0 commit comments