- 
  Notifications
 
You must be signed in to change notification settings  - Fork 0
 
refactor(auth): introduce _ensureUserDataExists to handle default doc... #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
 
  Merged
 
 
 fulleni
 merged 1 commit into
 main 
from
fix_new_user_unprepared_settings_and_preferences 
 
 
 
  
 Jul 19, 2025 
 
 
 
  Merged
 Changes from all commits
 Commits
 
 
 File filter
Filter by extension
Conversations
 Failed to load comments. 
 
 
 
  Loading
 
 Jump to
 
 Jump to file
 
 
 
 Failed to load files. 
 
 
 
  Loading
 
 Diff view
Diff view
There are no files selected for viewing
 
 
 This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
 Learn more about bidirectional Unicode characters
 
 
 
 
 | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| 
 
 
 
  | 
 @@ -229,45 +229,8 @@ class AuthService { | |
| user = await _userRepository.create(item: user); | ||
| _log.info('Created new user: ${user.id} with appRole: ${user.appRole}'); | ||
| 
  | 
||
| // Create default UserAppSettings for the new user | ||
| final defaultAppSettings = UserAppSettings( | ||
| id: user.id, | ||
| displaySettings: const DisplaySettings( | ||
| baseTheme: AppBaseTheme.system, | ||
| accentTheme: AppAccentTheme.defaultBlue, | ||
| fontFamily: 'SystemDefault', | ||
| textScaleFactor: AppTextScaleFactor.medium, | ||
| fontWeight: AppFontWeight.regular, | ||
| ), | ||
| language: 'en', | ||
| feedPreferences: const FeedDisplayPreferences( | ||
| headlineDensity: HeadlineDensity.standard, | ||
| headlineImageStyle: HeadlineImageStyle.largeThumbnail, | ||
| showSourceInHeadlineFeed: true, | ||
| showPublishDateInHeadlineFeed: true, | ||
| ), | ||
| ); | ||
| await _userAppSettingsRepository.create( | ||
| item: defaultAppSettings, | ||
| userId: user.id, | ||
| ); | ||
| _log.info('Created default UserAppSettings for user: ${user.id}'); | ||
| 
  | 
||
| // Create default UserContentPreferences for the new user | ||
| final defaultUserPreferences = UserContentPreferences( | ||
| id: user.id, | ||
| followedCountries: const [], | ||
| followedSources: const [], | ||
| followedTopics: const [], | ||
| savedHeadlines: const [], | ||
| ); | ||
| await _userContentPreferencesRepository.create( | ||
| item: defaultUserPreferences, | ||
| userId: user.id, | ||
| ); | ||
| _log.info( | ||
| 'Created default UserContentPreferences for user: ${user.id}', | ||
| ); | ||
| // Ensure default documents are created for the new user. | ||
| await _ensureUserDataExists(user); | ||
| } | ||
| } on HtHttpException { | ||
| // Propagate known exceptions from dependencies or from this method's logic. | ||
| 
 
 
 
  | 
 @@ -322,6 +285,9 @@ class AuthService { | |
| ); | ||
| user = await _userRepository.create(item: user); | ||
| _log.info('Created anonymous user: ${user.id}'); | ||
| 
  | 
||
| // Ensure default documents are created for the new anonymous user. | ||
| await _ensureUserDataExists(user); | ||
| } on HtHttpException catch (e) { | ||
| _log.severe('Error creating anonymous user: $e'); | ||
| throw const OperationFailedException('Failed to create anonymous user.'); | ||
| 
 
 
 
  | 
 @@ -332,46 +298,6 @@ class AuthService { | |
| ); | ||
| } | ||
| 
  | 
||
| // Create default UserAppSettings for the new anonymous user | ||
| final defaultAppSettings = UserAppSettings( | ||
| id: user.id, | ||
| displaySettings: const DisplaySettings( | ||
| baseTheme: AppBaseTheme.system, | ||
| accentTheme: AppAccentTheme.defaultBlue, | ||
| fontFamily: 'SystemDefault', | ||
| textScaleFactor: AppTextScaleFactor.medium, | ||
| fontWeight: AppFontWeight.regular, | ||
| ), | ||
| language: 'en', | ||
| feedPreferences: const FeedDisplayPreferences( | ||
| headlineDensity: HeadlineDensity.standard, | ||
| headlineImageStyle: HeadlineImageStyle.largeThumbnail, | ||
| showSourceInHeadlineFeed: true, | ||
| showPublishDateInHeadlineFeed: true, | ||
| ), | ||
| ); | ||
| await _userAppSettingsRepository.create( | ||
| item: defaultAppSettings, | ||
| userId: user.id, // Pass user ID for scoping | ||
| ); | ||
| _log.info('Created default UserAppSettings for anonymous user: ${user.id}'); | ||
| 
  | 
||
| // Create default UserContentPreferences for the new anonymous user | ||
| final defaultUserPreferences = UserContentPreferences( | ||
| id: user.id, | ||
| followedCountries: const [], | ||
| followedSources: const [], | ||
| followedTopics: const [], | ||
| savedHeadlines: const [], | ||
| ); | ||
| await _userContentPreferencesRepository.create( | ||
| item: defaultUserPreferences, | ||
| userId: user.id, // Pass user ID for scoping | ||
| ); | ||
| _log.info( | ||
| 'Created default UserContentPreferences for anonymous user: ${user.id}', | ||
| ); | ||
| 
  | 
||
| // 2. Generate token | ||
| try { | ||
| final token = await _authTokenService.generateToken(user); | ||
| 
 
 
 
  | 
 @@ -541,6 +467,9 @@ class AuthService { | |
| 'User ${permanentUser.id} successfully linked with email $linkedEmail.', | ||
| ); | ||
| 
  | 
||
| // Ensure user data exists after linking. | ||
| await _ensureUserDataExists(permanentUser); | ||
| 
  | 
||
| // 3. Generate a new authentication token for the now-permanent user. | ||
| final newToken = await _authTokenService.generateToken(permanentUser); | ||
| _log.info('Generated new token for linked user ${permanentUser.id}'); | ||
| 
 
 
 
  | 
 @@ -666,4 +595,62 @@ class AuthService { | |
| rethrow; | ||
| } | ||
| } | ||
| 
  | 
||
| /// Ensures that the essential user-specific documents (settings, preferences) | ||
| /// exist for a given user, creating them with default values if they are missing. | ||
| /// | ||
| /// This method is crucial for maintaining data integrity, especially for users | ||
| /// who might have been created before these documents were part of the standard | ||
| /// user creation process. | ||
| Future<void> _ensureUserDataExists(User user) async { | ||
| // Check for UserAppSettings | ||
| try { | ||
| await _userAppSettingsRepository.read(id: user.id, userId: user.id); | ||
| } on NotFoundException { | ||
| _log.info( | ||
| 'UserAppSettings not found for user ${user.id}. Creating with defaults.', | ||
| ); | ||
| final defaultAppSettings = UserAppSettings( | ||
| id: user.id, | ||
| displaySettings: const DisplaySettings( | ||
| baseTheme: AppBaseTheme.system, | ||
| accentTheme: AppAccentTheme.defaultBlue, | ||
| fontFamily: 'SystemDefault', | ||
| textScaleFactor: AppTextScaleFactor.medium, | ||
| fontWeight: AppFontWeight.regular, | ||
| ), | ||
| language: 'en', | ||
| feedPreferences: const FeedDisplayPreferences( | ||
| headlineDensity: HeadlineDensity.standard, | ||
| headlineImageStyle: HeadlineImageStyle.largeThumbnail, | ||
| showSourceInHeadlineFeed: true, | ||
| showPublishDateInHeadlineFeed: true, | ||
| ), | ||
| ); | ||
| await _userAppSettingsRepository.create( | ||
| item: defaultAppSettings, | ||
| userId: user.id, | ||
| ); | ||
| } | ||
| 
  | 
||
| // Check for UserContentPreferences | ||
| try { | ||
| await _userContentPreferencesRepository.read(id: user.id, userId: user.id); | ||
| } on NotFoundException { | ||
| _log.info( | ||
| 'UserContentPreferences not found for user ${user.id}. Creating with defaults.', | ||
| ); | ||
| final defaultUserPreferences = UserContentPreferences( | ||
| id: user.id, | ||
| followedCountries: const [], | ||
| followedSources: const [], | ||
| followedTopics: const [], | ||
| savedHeadlines: const [], | ||
| ); | ||
| await _userContentPreferencesRepository.create( | ||
| item: defaultUserPreferences, | ||
| userId: user.id, | ||
| ); | ||
| } | ||
| } | ||
| 
  
 Comment on lines
 
 +605
  to 
 +655
 
  
 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The checks for   | 
||
| } | ||
 
 Oops, something went wrong.
 
 
 
 Add this suggestion to a batch that can be applied as a single commit.
 This suggestion is invalid because no changes were made to the code.
 Suggestions cannot be applied while the pull request is closed.
 Suggestions cannot be applied while viewing a subset of changes.
 Only one suggestion per line can be applied in a batch.
 Add this suggestion to a batch that can be applied as a single commit.
 Applying suggestions on deleted lines is not supported.
 You must change the existing code in this line in order to create a valid suggestion.
 Outdated suggestions cannot be applied.
 This suggestion has been applied or marked resolved.
 Suggestions cannot be applied from pending reviews.
 Suggestions cannot be applied on multi-line comments.
 Suggestions cannot be applied while the pull request is queued to merge.
 Suggestion cannot be applied right now. Please check back later.