@@ -121,8 +121,6 @@ class DataOperationRegistry {
121121 c.read <DataRepository <RemoteConfig >>().read (id: id, userId: null ),
122122 'dashboard_summary' : (c, id) =>
123123 c.read <DashboardSummaryService >().getSummary (),
124- 'interest' : (c, id) =>
125- c.read <DataRepository <Interest >>().read (id: id, userId: null ),
126124 'in_app_notification' : (c, id) => c
127125 .read <DataRepository <InAppNotification >>()
128126 .read (id: id, userId: null ),
@@ -170,13 +168,6 @@ class DataOperationRegistry {
170168 .read <DataRepository <Language >>()
171169 .readAll (userId: uid, filter: f, sort: s, pagination: p),
172170 'user' : (c, uid, f, s, p) => c.read <DataRepository <User >>().readAll (
173- userId: uid,
174- filter: f,
175- sort: s,
176- pagination: p,
177- ),
178- 'interest' : (c, uid, f, s, p) =>
179- c.read <DataRepository <Interest >>().readAll (
180171 userId: uid,
181172 filter: f,
182173 sort: s,
@@ -277,30 +268,6 @@ class DataOperationRegistry {
277268 userId: null ,
278269 );
279270 },
280- 'interest' : (context, item, uid) async {
281- _log.info ('Executing custom creator for interest.' );
282- final authenticatedUser = context.read <User >();
283- final interestToCreate = (item as Interest ).copyWith (
284- userId: authenticatedUser.id,
285- );
286-
287- // 1. Fetch current user preferences to get existing interests.
288- final preferences = await context
289- .read <DataRepository <UserContentPreferences >>()
290- .read (id: authenticatedUser.id);
291-
292- // 2. Check limits before creating.
293- await context.read <UserPreferenceLimitService >().checkInterestLimits (
294- user: authenticatedUser,
295- interest: interestToCreate,
296- existingInterests: preferences.interests,
297- );
298-
299- // 3. Proceed with creation.
300- return context.read <DataRepository <Interest >>().create (
301- item: interestToCreate,
302- );
303- },
304271 });
305272
306273 // --- Register Item Updaters ---
@@ -419,53 +386,111 @@ class DataOperationRegistry {
419386 'Executing custom updater for user_content_preferences ID: $id .' ,
420387 );
421388 final authenticatedUser = context.read <User >();
422- final preferencesToUpdate = item as UserContentPreferences ;
389+ final userPreferenceLimitService =
390+ context.read <UserPreferenceLimitService >();
391+ final userContentPreferencesRepository =
392+ context.read <DataRepository <UserContentPreferences >>();
423393
424- // 1. Check limits before updating.
425- await context
426- .read <UserPreferenceLimitService >()
427- .checkUserContentPreferencesLimits (
428- user: authenticatedUser,
429- updatedPreferences: preferencesToUpdate,
430- );
394+ final preferencesToUpdate = item as UserContentPreferences ;
431395
432- // 2. Proceed with update .
433- return context .read < DataRepository < UserContentPreferences >>(). update (
396+ // 1. Fetch the current state of the user's preferences .
397+ final currentPreferences = await userContentPreferencesRepository .read (
434398 id: id,
435- item: preferencesToUpdate,
436399 );
437- },
438- 'remote_config' : (c, id, item, uid) => c
439- .read <DataRepository <RemoteConfig >>()
440- .update (id: id, item: item as RemoteConfig , userId: uid),
441- 'interest' : (context, id, item, uid) async {
442- _log.info ('Executing custom updater for interest ID: $id .' );
443- final authenticatedUser = context.read <User >();
444- final interestToUpdate = item as Interest ;
445400
446- // 1. Fetch current user preferences to get existing interests.
447- final preferences = await context
448- .read <DataRepository <UserContentPreferences >>()
449- .read (id: authenticatedUser.id);
401+ // 2. Detect changes in the interests list.
402+ final currentIds =
403+ currentPreferences.interests.map ((i) => i.id).toSet ();
404+ final updatedIds =
405+ preferencesToUpdate.interests.map ((i) => i.id).toSet ();
450406
451- // Exclude the interest being updated from the list for limit checking.
452- final otherInterests = preferences.interests
453- .where ((i) => i.id != id)
454- .toList ();
407+ final addedIds = updatedIds.difference (currentIds);
408+ final removedIds = currentIds.difference (updatedIds);
455409
456- // 2. Check limits before updating.
457- await context.read <UserPreferenceLimitService >().checkInterestLimits (
410+ // For simplicity and clear validation, enforce one change at a time.
411+ if (addedIds.length + removedIds.length > 1 ) {
412+ throw const BadRequestException (
413+ 'Only one interest can be added or removed per request.' ,
414+ );
415+ }
416+
417+ // 3. Perform permission and limit checks based on the detected action.
418+ if (addedIds.isNotEmpty) {
419+ // --- Interest Added ---
420+ final addedInterestId = addedIds.first;
421+ _log.info (
422+ 'Detected interest addition for user ${authenticatedUser .id }.' ,
423+ );
424+
425+ final addedInterest = preferencesToUpdate.interests
426+ .firstWhere ((i) => i.id == addedInterestId);
427+
428+ // Check business logic limits.
429+ await userPreferenceLimitService.checkInterestLimits (
430+ user: authenticatedUser,
431+ interest: addedInterest,
432+ existingInterests: currentPreferences.interests,
433+ );
434+ } else if (removedIds.isNotEmpty) {
435+ // --- Interest Removed ---
436+ _log.info (
437+ 'Detected interest removal for user ${authenticatedUser .id }.' ,
438+ );
439+
440+ } else {
441+ // --- Interest Potentially Updated ---
442+ // Check if any existing interest was modified.
443+ Interest ? updatedInterest;
444+ for (final newInterest in preferencesToUpdate.interests) {
445+ // Find the corresponding interest in the old list.
446+ final oldInterest = currentPreferences.interests.firstWhere (
447+ (i) => i.id == newInterest.id,
448+ // This should not be hit if add/remove is handled, but as a
449+ // safeguard, we use the newInterest to avoid null issues.
450+ orElse: () => newInterest,
451+ );
452+ if (newInterest != oldInterest) {
453+ updatedInterest = newInterest;
454+ break ; // Found the updated one, no need to continue loop.
455+ }
456+ }
457+
458+ if (updatedInterest != null ) {
459+ _log.info (
460+ 'Detected interest update for user ${authenticatedUser .id }.' ,
461+ );
462+
463+ // Check business logic limits.
464+ final otherInterests = currentPreferences.interests
465+ .where ((i) => i.id != updatedInterest! .id)
466+ .toList ();
467+ await userPreferenceLimitService.checkInterestLimits (
468+ user: authenticatedUser,
469+ interest: updatedInterest,
470+ existingInterests: otherInterests,
471+ );
472+ }
473+ }
474+
475+ // 4. Always validate general preference limits (followed items, etc.).
476+ await userPreferenceLimitService.checkUserContentPreferencesLimits (
458477 user: authenticatedUser,
459- interest: interestToUpdate,
460- existingInterests: otherInterests,
478+ updatedPreferences: preferencesToUpdate,
461479 );
462480
463- // 3. Proceed with update.
464- return context.read <DataRepository <Interest >>().update (
481+ // 5. If all checks pass, proceed with the update.
482+ _log.info (
483+ 'All preference validations passed for user ${authenticatedUser .id }. '
484+ 'Proceeding with update.' ,
485+ );
486+ return userContentPreferencesRepository.update (
465487 id: id,
466- item: interestToUpdate ,
488+ item: preferencesToUpdate ,
467489 );
468490 },
491+ 'remote_config' : (c, id, item, uid) => c
492+ .read <DataRepository <RemoteConfig >>()
493+ .update (id: id, item: item as RemoteConfig , userId: uid),
469494 });
470495
471496 // --- Register Item Deleters ---
@@ -490,8 +515,6 @@ class DataOperationRegistry {
490515 'push_notification_device' : (c, id, uid) => c
491516 .read <DataRepository <PushNotificationDevice >>()
492517 .delete (id: id, userId: uid),
493- 'interest' : (c, id, uid) =>
494- c.read <DataRepository <Interest >>().delete (id: id, userId: uid),
495518 'in_app_notification' : (c, id, uid) => c
496519 .read <DataRepository <InAppNotification >>()
497520 .delete (id: id, userId: uid),
0 commit comments