From 696b8725883d893ec3d9fe3a1414a76826989eba Mon Sep 17 00:00:00 2001 From: fulleni Date: Sat, 19 Jul 2025 07:31:00 +0100 Subject: [PATCH] refactor(auth): introduce _ensureUserDataExists to handle default documents creation - Introduce new private method _ensureUserDataExists to centralize the logic for creating default UserAppSettings and UserContentPreferences - Replace inline creation logic with calls to _ensureUserDataExists for both registered and anonymous users - Add error handling to check for existing documents before creation, preventing duplicates --- lib/src/services/auth_service.dart | 145 +++++++++++++---------------- 1 file changed, 66 insertions(+), 79 deletions(-) diff --git a/lib/src/services/auth_service.dart b/lib/src/services/auth_service.dart index 0e36559..df98aad 100644 --- a/lib/src/services/auth_service.dart +++ b/lib/src/services/auth_service.dart @@ -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 _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, + ); + } + } }