Skip to content

Commit 40a8019

Browse files
committed
fix(auth): correct user creation and deletion logic
- Fixes a bug where `UserAppSettings` and `UserContentPreferences` were created without required default values for new and anonymous users. - Implements the account deletion cleanup logic. Deleting a user from the `users` table now correctly cascades to delete their associated settings and preferences, and any pending verification codes are cleared.
1 parent 6a82d95 commit 40a8019

File tree

1 file changed

+72
-22
lines changed

1 file changed

+72
-22
lines changed

lib/src/services/auth_service.dart

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -193,15 +193,37 @@ class AuthService {
193193
);
194194

195195
// Create default UserAppSettings for the new user
196-
final defaultAppSettings = UserAppSettings(id: user.id);
196+
final defaultAppSettings = UserAppSettings(
197+
id: user.id,
198+
displaySettings: const DisplaySettings(
199+
baseTheme: AppBaseTheme.system,
200+
accentTheme: AppAccentTheme.defaultBlue,
201+
fontFamily: 'SystemDefault',
202+
textScaleFactor: AppTextScaleFactor.medium,
203+
fontWeight: AppFontWeight.regular,
204+
),
205+
language: 'en',
206+
feedPreferences: const FeedDisplayPreferences(
207+
headlineDensity: HeadlineDensity.normal,
208+
headlineImageStyle: HeadlineImageStyle.largeThumbnail,
209+
showSourceInHeadlineFeed: true,
210+
showPublishDateInHeadlineFeed: true,
211+
),
212+
);
197213
await _userAppSettingsRepository.create(
198214
item: defaultAppSettings,
199215
userId: user.id,
200216
);
201217
_log.info('Created default UserAppSettings for user: ${user.id}');
202218

203219
// Create default UserContentPreferences for the new user
204-
final defaultUserPreferences = UserContentPreferences(id: user.id);
220+
final defaultUserPreferences = UserContentPreferences(
221+
id: user.id,
222+
followedCountries: const [],
223+
followedSources: const [],
224+
followedTopics: const [],
225+
savedHeadlines: const [],
226+
);
205227
await _userContentPreferencesRepository.create(
206228
item: defaultUserPreferences,
207229
userId: user.id,
@@ -270,15 +292,37 @@ class AuthService {
270292
}
271293

272294
// Create default UserAppSettings for the new anonymous user
273-
final defaultAppSettings = UserAppSettings(id: user.id);
295+
final defaultAppSettings = UserAppSettings(
296+
id: user.id,
297+
displaySettings: const DisplaySettings(
298+
baseTheme: AppBaseTheme.system,
299+
accentTheme: AppAccentTheme.defaultBlue,
300+
fontFamily: 'SystemDefault',
301+
textScaleFactor: AppTextScaleFactor.medium,
302+
fontWeight: AppFontWeight.regular,
303+
),
304+
language: 'en',
305+
feedPreferences: const FeedDisplayPreferences(
306+
headlineDensity: HeadlineDensity.normal,
307+
headlineImageStyle: HeadlineImageStyle.largeThumbnail,
308+
showSourceInHeadlineFeed: true,
309+
showPublishDateInHeadlineFeed: true,
310+
),
311+
);
274312
await _userAppSettingsRepository.create(
275313
item: defaultAppSettings,
276314
userId: user.id, // Pass user ID for scoping
277315
);
278316
_log.info('Created default UserAppSettings for anonymous user: ${user.id}');
279317

280318
// Create default UserContentPreferences for the new anonymous user
281-
final defaultUserPreferences = UserContentPreferences(id: user.id);
319+
final defaultUserPreferences = UserContentPreferences(
320+
id: user.id,
321+
followedCountries: const [],
322+
followedSources: const [],
323+
followedTopics: const [],
324+
savedHeadlines: const [],
325+
);
282326
await _userContentPreferencesRepository.create(
283327
item: defaultUserPreferences,
284328
userId: user.id, // Pass user ID for scoping
@@ -509,13 +553,21 @@ class AuthService {
509553
/// Throws [NotFoundException] if the user does not exist.
510554
/// Throws [OperationFailedException] for other errors during deletion or cleanup.
511555
Future<void> deleteAccount({required String userId}) async {
556+
// Note: The user record itself is deleted via a CASCADE constraint
557+
// when the corresponding entry in the `users` table is deleted.
558+
// This is because `user_app_settings.user_id` and
559+
// `user_content_preferences.user_id` have `ON DELETE CASCADE`.
560+
// Therefore, we only need to delete the main user record.
512561
try {
513562
// Fetch the user first to get their email if needed for cleanup
514563
final userToDelete = await _userRepository.read(id: userId);
515564
_log.info('Found user ${userToDelete.id} for deletion.');
516565

517-
// 1. Delete the user record from the repository.
518-
// This implicitly invalidates tokens that rely on user lookup.
566+
// 1. Delete the main user record from the `users` table.
567+
// The `ON DELETE CASCADE` constraint on the `user_app_settings` and
568+
// `user_content_preferences` tables will automatically delete the
569+
// associated records in those tables. This also implicitly invalidates
570+
// tokens that rely on user lookup, as the user will no longer exist.
519571
await _userRepository.delete(id: userId);
520572
_log.info('User ${userToDelete.id} deleted from repository.');
521573

@@ -531,23 +583,21 @@ class AuthService {
531583
}
532584

533585
// 3. Clear any pending sign-in codes for the user's email (if they had one).
534-
try {
535-
await _verificationCodeStorageService.clearSignInCode(
536-
userToDelete.email,
537-
);
538-
_log.info(
539-
'Cleared sign-in code for email ${userToDelete.email}.',
540-
);
541-
} catch (e) {
542-
// Log but don't fail deletion if clearing codes fails
543-
_log.warning(
544-
'Warning: Failed to clear sign-in code for email ${userToDelete.email}: $e',
545-
);
586+
// The email for anonymous users is a placeholder and not used for sign-in.
587+
if (userToDelete.appRole != AppUserRole.guestUser) {
588+
try {
589+
await _verificationCodeStorageService.clearSignInCode(
590+
userToDelete.email,
591+
);
592+
_log.info(
593+
'Cleared sign-in code for email ${userToDelete.email}.',
594+
);
595+
} catch (e) {
596+
_log.warning(
597+
'Warning: Failed to clear sign-in code for email ${userToDelete.email}: $e',
598+
);
599+
}
546600
}
547-
548-
// TODO(fulleni): Add logic here to delete or anonymize other
549-
// user-related data (e.g., settings, content) from other repositories
550-
// once those features are implemented.
551601

552602
_log.info(
553603
'Account deletion process completed for user $userId.',

0 commit comments

Comments
 (0)