From 60e67257a8c05508c319cafd246f273a90f7ef65 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 04:28:25 +0100 Subject: [PATCH 1/4] chore(deps): update core package reference - Updated core package reference from 8bae6eb to e66e076 in pubspec.yaml - Updated corresponding reference in pubspec.lock --- pubspec.lock | 4 ++-- pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 6fc6de9..b5fa979 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -181,8 +181,8 @@ packages: dependency: "direct main" description: path: "." - ref: "8bae6eb17369b76f72961870a22ee13d3073fa61" - resolved-ref: "8bae6eb17369b76f72961870a22ee13d3073fa61" + ref: e66e076572bd326e50e9d5286ef5059ff658ed65 + resolved-ref: e66e076572bd326e50e9d5286ef5059ff658ed65 url: "https://github.com/flutter-news-app-full-source-code/core.git" source: git version: "1.3.1" diff --git a/pubspec.yaml b/pubspec.yaml index a8dfd86..951b990 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -62,7 +62,7 @@ dependency_overrides: core: git: url: https://github.com/flutter-news-app-full-source-code/core.git - ref: 8bae6eb17369b76f72961870a22ee13d3073fa61 + ref: e66e076572bd326e50e9d5286ef5059ff658ed65 data_mongodb: git: url: https://github.com/flutter-news-app-full-source-code/data-mongodb.git From 023a3c0d7d113858dc8d82f0525447668e66a77d Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 04:41:07 +0100 Subject: [PATCH 2/4] feat(engagement): implement single engagement per user and entity - Add a business logic check to prevent multiple engagements by the same user for the same entity - Query existing engagements for the authenticated user and the entity in question - Throw a ConflictException if an existing engagement is found - Log a warning message when attempting to create a duplicate engagement --- lib/src/registry/data_operation_registry.dart | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/src/registry/data_operation_registry.dart b/lib/src/registry/data_operation_registry.dart index c5574e0..41949dd 100644 --- a/lib/src/registry/data_operation_registry.dart +++ b/lib/src/registry/data_operation_registry.dart @@ -318,6 +318,24 @@ class DataOperationRegistry { ); } + // Business Logic Check: Ensure a user can only have one engagement + // per headline to prevent duplicate reactions or comments. + final engagementRepository = context.read>(); + final existingEngagements = await engagementRepository.readAll( + filter: { + 'userId': authenticatedUser.id, + 'entityId': engagementToCreate.entityId, + 'entityType': engagementToCreate.entityType.name, + }, + ); + + if (existingEngagements.items.isNotEmpty) { + _log.warning( + 'User ${authenticatedUser.id} attempted to create a second engagement for entity ${engagementToCreate.entityId}.', + ); + throw const ConflictException('An engagement for this item already exists.'); + } + // Limit Check: Delegate to the centralized service. await userActionLimitService.checkEngagementCreationLimit( user: authenticatedUser, From 099f8ea8e5ea7b63b2370cb66dbdff1d0db8b3c8 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 04:41:32 +0100 Subject: [PATCH 3/4] fix(limits): improve reaction limit check in user action service - Add condition to check reaction limit only if a reaction is present - Update database query to count only engagements with reactions - Refactor code to make reaction limit check more precise and efficient --- .../default_user_action_limit_service.dart | 44 ++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/lib/src/services/default_user_action_limit_service.dart b/lib/src/services/default_user_action_limit_service.dart index ca72890..9674eb1 100644 --- a/lib/src/services/default_user_action_limit_service.dart +++ b/lib/src/services/default_user_action_limit_service.dart @@ -265,24 +265,35 @@ class DefaultUserActionLimitService implements UserActionLimitService { ); } - // Count all engagements in the last 24 hours for the reaction limit. - final twentyFourHoursAgo = DateTime.now().subtract( - const Duration(hours: 24), - ); - final reactionCount = await _engagementRepository.count( - filter: { - 'userId': user.id, - 'createdAt': {r'$gte': twentyFourHoursAgo.toIso8601String()}, - }, - ); + // --- 1. Check Reaction Limit (only if a reaction is present) --- + if (engagement.reaction != null) { + final reactionsLimit = limits.reactionsPerDay[user.appRole]; + if (reactionsLimit == null) { + throw StateError( + 'Reactions per day limit not configured for role: ${user.appRole}', + ); + } - if (reactionCount >= reactionsLimit) { - _log.warning( - 'User ${user.id} exceeded reactions per day limit: $reactionsLimit.', + // Count engagements with reactions in the last 24 hours. + final twentyFourHoursAgo = DateTime.now().subtract( + const Duration(hours: 24), ); - throw const ForbiddenException( - 'You have reached your daily limit for reactions.', + final reactionCount = await _engagementRepository.count( + filter: { + 'userId': user.id, + 'reaction': {r'$exists': true, r'$ne': null}, + 'createdAt': {r'$gte': twentyFourHoursAgo.toIso8601String()}, + }, ); + + if (reactionCount >= reactionsLimit) { + _log.warning( + 'User ${user.id} exceeded reactions per day limit: $reactionsLimit.', + ); + throw const ForbiddenException( + 'You have reached your daily limit for reactions.', + ); + } } // --- 2. Check Comment Limit (only if a comment is present) --- @@ -295,6 +306,9 @@ class DefaultUserActionLimitService implements UserActionLimitService { } // Count engagements with comments in the last 24 hours. + final twentyFourHoursAgo = DateTime.now().subtract( + const Duration(hours: 24), + ); final commentCount = await _engagementRepository.count( filter: { 'userId': user.id, From b28f8d3eb8bb5014a13a4134dbf087fc7040ee36 Mon Sep 17 00:00:00 2001 From: fulleni Date: Fri, 5 Dec 2025 04:43:12 +0100 Subject: [PATCH 4/4] style: format --- lib/src/registry/data_operation_registry.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/src/registry/data_operation_registry.dart b/lib/src/registry/data_operation_registry.dart index 41949dd..a0533a7 100644 --- a/lib/src/registry/data_operation_registry.dart +++ b/lib/src/registry/data_operation_registry.dart @@ -333,7 +333,9 @@ class DataOperationRegistry { _log.warning( 'User ${authenticatedUser.id} attempted to create a second engagement for entity ${engagementToCreate.entityId}.', ); - throw const ConflictException('An engagement for this item already exists.'); + throw const ConflictException( + 'An engagement for this item already exists.', + ); } // Limit Check: Delegate to the centralized service.