This is an automated email from the ASF dual-hosted git repository.
arnold pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new d21110f7b FINERACT-1724: Put user notification feature behind feature
toggle
d21110f7b is described below
commit d21110f7b26298a40278e0c120586f3a96d0d1fa
Author: Adam Saghy <[email protected]>
AuthorDate: Wed Mar 22 19:12:31 2023 +0100
FINERACT-1724: Put user notification feature behind feature toggle
---
.../core/config/FineractProperties.java | 15 +++
.../TenantAwareBasicAuthenticationFilter.java | 6 +-
.../NotificationEventListener.java | 33 +-----
.../service/NotificationDomainServiceImpl.java | 29 +-----
.../service/NotificationWritePlatformService.java | 3 -
.../NotificationWritePlatformServiceImpl.java | 20 ----
...rmService.java => UserNotificationService.java} | 13 +--
.../service/UserNotificationServiceImpl.java | 114 +++++++++++++++++++++
.../src/main/resources/application.properties | 2 +
9 files changed, 146 insertions(+), 89 deletions(-)
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
index bcf601ab8..7348d52e2 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
@@ -58,6 +58,8 @@ public class FineractProperties {
private FineractQueryProperties query;
private FineractApiProperties api;
+ private FineractNotificationProperties notification;
+
@Getter
@Setter
public static class FineractTenantProperties {
@@ -280,4 +282,17 @@ public class FineractProperties {
private int inlineLoanCob;
}
+ @Getter
+ @Setter
+ public static class FineractNotificationProperties {
+
+ private UserNotificationSystemProperties userNotificationSystem;
+ }
+
+ @Getter
+ @Setter
+ public static class UserNotificationSystemProperties {
+
+ private boolean enabled;
+ }
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
index d9a43c437..3709ec45d 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
@@ -37,7 +37,7 @@ import
org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.security.data.PlatformRequestLog;
import
org.apache.fineract.infrastructure.security.exception.InvalidTenantIdentifierException;
import
org.apache.fineract.infrastructure.security.service.BasicAuthTenantDetailsService;
-import
org.apache.fineract.notification.service.NotificationReadPlatformService;
+import org.apache.fineract.notification.service.UserNotificationService;
import org.apache.fineract.useradministration.domain.AppUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -79,7 +79,7 @@ public class TenantAwareBasicAuthenticationFilter extends
BasicAuthenticationFil
private CacheWritePlatformService cacheWritePlatformService;
@Autowired
- private NotificationReadPlatformService notificationReadPlatformService;
+ private UserNotificationService userNotificationService;
@Autowired
private BasicAuthTenantDetailsService basicAuthTenantDetailsService;
@@ -170,7 +170,7 @@ public class TenantAwareBasicAuthenticationFilter extends
BasicAuthenticationFil
super.onSuccessfulAuthentication(request, response, authResult);
AppUser user = (AppUser) authResult.getPrincipal();
- if
(notificationReadPlatformService.hasUnreadNotifications(user.getId())) {
+ if (userNotificationService.hasUnreadUserNotifications(user.getId())) {
response.addHeader("X-Notification-Refresh", "true");
} else {
response.addHeader("X-Notification-Refresh", "false");
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventListener.java
b/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventListener.java
index 31dc3cbe9..75eb78f58 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventListener.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventListener.java
@@ -18,46 +18,19 @@
*/
package org.apache.fineract.notification.eventandlistener;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.notification.data.NotificationData;
-import
org.apache.fineract.notification.service.NotificationWritePlatformService;
-import org.apache.fineract.useradministration.domain.AppUser;
-import org.apache.fineract.useradministration.domain.AppUserRepository;
+import org.apache.fineract.notification.service.UserNotificationService;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class NotificationEventListener {
- private final NotificationWritePlatformService
notificationWritePlatformService;
- private final AppUserRepository appUserRepository;
+ private final UserNotificationService userNotificationService;
public void receive(NotificationData notificationData) {
- Long appUserId = notificationData.getActorId();
+ userNotificationService.notifyUsers(notificationData);
- Set<Long> userIds = notificationData.getUserIds();
-
- if (notificationData.getOfficeId() != null) {
- List<Long> tempUserIds = new ArrayList<>(userIds);
- for (Long userId : tempUserIds) {
- AppUser appUser =
appUserRepository.findById(userId).orElseThrow();
- if (!Objects.equals(appUser.getOffice().getId(),
notificationData.getOfficeId())) {
- userIds.remove(userId);
- }
- }
- }
-
- // Don't notify the same user who triggered the event
- if (userIds.contains(appUserId)) {
- userIds.remove(appUserId);
- }
-
- notificationWritePlatformService.notify(userIds,
notificationData.getObjectType(), notificationData.getObjectId(),
- notificationData.getAction(), notificationData.getActorId(),
notificationData.getContent(),
- notificationData.isSystemGenerated());
}
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainServiceImpl.java
index 1fcb893a7..750452359 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainServiceImpl.java
@@ -18,15 +18,10 @@
*/
package org.apache.fineract.notification.service;
-import static java.util.stream.Collectors.toSet;
-
-import java.util.Collection;
-import java.util.Set;
import javax.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
-import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.event.business.BusinessEventListener;
import
org.apache.fineract.infrastructure.event.business.domain.client.ClientCreateBusinessEvent;
import
org.apache.fineract.infrastructure.event.business.domain.deposit.FixedDepositAccountCreateBusinessEvent;
@@ -50,8 +45,6 @@ import
org.apache.fineract.infrastructure.event.business.domain.share.ShareAccou
import
org.apache.fineract.infrastructure.event.business.domain.share.ShareProductDividentsCreateBusinessEvent;
import
org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
-import org.apache.fineract.notification.data.NotificationData;
-import
org.apache.fineract.notification.eventandlistener.NotificationEventPublisher;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
@@ -62,8 +55,6 @@ import
org.apache.fineract.portfolio.savings.domain.RecurringDepositAccount;
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccount;
-import org.apache.fineract.useradministration.domain.AppUser;
-import org.apache.fineract.useradministration.domain.AppUserRepository;
import org.springframework.stereotype.Service;
@Service
@@ -73,8 +64,7 @@ public class NotificationDomainServiceImpl implements
NotificationDomainService
private final BusinessEventNotifierService businessEventNotifierService;
private final PlatformSecurityContext context;
- private final NotificationEventPublisher notificationEventPublisher;
- private final AppUserRepository appUserRepository;
+ private final UserNotificationService userNotificationService;
@PostConstruct
public void addListeners() {
@@ -327,22 +317,7 @@ public class NotificationDomainServiceImpl implements
NotificationDomainService
private void buildNotification(String permission, String objectType, Long
objectIdentifier, String notificationContent,
String eventType, Long appUserId, Long officeId) {
- String tenantIdentifier =
ThreadLocalContextUtil.getTenant().getTenantIdentifier();
- Set<Long> userIds = getNotifiableUserIds(officeId, permission);
- NotificationData notificationData = new
NotificationData().setObjectType(objectType).setObjectId(objectIdentifier)
-
.setAction(eventType).setActorId(appUserId).setContent(notificationContent).setRead(false).setSystemGenerated(false)
-
.setTenantIdentifier(tenantIdentifier).setOfficeId(officeId).setUserIds(userIds);
- try {
- notificationEventPublisher.broadcastNotification(notificationData);
- } catch (Exception e) {
- // We want to avoid rethrowing the exception to stop the business
transaction from rolling back
- log.error("Error while broadcasting notification event", e);
- }
+ userNotificationService.notifyUsers(permission, objectType,
objectIdentifier, notificationContent, eventType, appUserId, officeId);
}
- private Set<Long> getNotifiableUserIds(Long officeId, String permission) {
- Collection<AppUser> users = appUserRepository.findByOfficeId(officeId);
- Collection<AppUser> usersWithPermission = users.stream().filter(aU ->
aU.hasAnyPermission(permission, "ALL_FUNCTIONS")).toList();
- return
usersWithPermission.stream().map(AppUser::getId).collect(toSet());
- }
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
index d0999baf6..65a38804c 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
@@ -22,9 +22,6 @@ import java.util.Collection;
public interface NotificationWritePlatformService {
- Long notify(Long userId, String objectType, Long objectId, String action,
Long actorId, String notificationContent,
- boolean isSystemGenerated);
-
Long notify(Collection<Long> userIds, String objectType, Long objectId,
String action, Long actorId, String notificationContent,
boolean isSystemGenerated);
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformServiceImpl.java
index 42105d9cc..e5a5b68f4 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformServiceImpl.java
@@ -40,26 +40,6 @@ public class NotificationWritePlatformServiceImpl implements
NotificationWritePl
private final AppUserRepository appUserRepository;
private final NotificationMapperWritePlatformService
notificationMapperWritePlatformService;
- @Override
- public Long notify(Long userId, String objectType, Long objectIdentifier,
String action, Long actorId, String notificationContent,
- boolean isSystemGenerated) {
-
- Long generatedNotificationId =
insertIntoNotificationGenerator(objectType, objectIdentifier, action, actorId,
notificationContent,
- isSystemGenerated);
- insertIntoNotificationMapper(userId, generatedNotificationId);
- return generatedNotificationId;
- }
-
- private Long insertIntoNotificationMapper(Long userId, Long
generatedNotificationId) {
- AppUser appUser = this.appUserRepository.findById(userId).orElse(null);
- NotificationMapper notificationMapper = new NotificationMapper()
-
.setNotification(this.notificationGeneratorReadRepositoryWrapper.findById(generatedNotificationId)).setUserId(appUser)
-
.setRead(false).setCreatedAt(DateUtils.getLocalDateTimeOfSystem());
-
- this.notificationMapperWritePlatformService.create(notificationMapper);
- return notificationMapper.getId();
- }
-
private Long insertIntoNotificationGenerator(String objectType, Long
objectIdentifier, String action, Long actorId,
String notificationContent, boolean isSystemGenerated) {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/UserNotificationService.java
similarity index 67%
copy from
fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
copy to
fineract-provider/src/main/java/org/apache/fineract/notification/service/UserNotificationService.java
index d0999baf6..06b9a6405 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/UserNotificationService.java
@@ -18,13 +18,14 @@
*/
package org.apache.fineract.notification.service;
-import java.util.Collection;
+import org.apache.fineract.notification.data.NotificationData;
-public interface NotificationWritePlatformService {
+public interface UserNotificationService {
- Long notify(Long userId, String objectType, Long objectId, String action,
Long actorId, String notificationContent,
- boolean isSystemGenerated);
+ void notifyUsers(String permission, String objectType, Long
objectIdentifier, String notificationContent, String eventType,
+ Long appUserId, Long officeId);
- Long notify(Collection<Long> userIds, String objectType, Long objectId,
String action, Long actorId, String notificationContent,
- boolean isSystemGenerated);
+ boolean hasUnreadUserNotifications(Long appUserId);
+
+ void notifyUsers(NotificationData notificationData);
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/UserNotificationServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/UserNotificationServiceImpl.java
new file mode 100644
index 000000000..f597aa4a1
--- /dev/null
+++
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/UserNotificationServiceImpl.java
@@ -0,0 +1,114 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.notification.service;
+
+import static java.util.stream.Collectors.toSet;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.fineract.infrastructure.core.config.FineractProperties;
+import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
+import org.apache.fineract.notification.data.NotificationData;
+import
org.apache.fineract.notification.eventandlistener.NotificationEventPublisher;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.apache.fineract.useradministration.domain.AppUserRepository;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class UserNotificationServiceImpl implements UserNotificationService {
+
+ private final NotificationEventPublisher notificationEventPublisher;
+ private final AppUserRepository appUserRepository;
+ private final FineractProperties fineractProperties;
+ private final NotificationReadPlatformService
notificationReadPlatformService;
+ private final NotificationWritePlatformService
notificationWritePlatformService;
+
+ @Override
+ public void notifyUsers(String permission, String objectType, Long
objectIdentifier, String notificationContent, String eventType,
+ Long appUserId, Long officeId) {
+
+ if (userNotificationSystemIsEnabled()) {
+ String tenantIdentifier =
ThreadLocalContextUtil.getTenant().getTenantIdentifier();
+ Set<Long> userIds = getNotifiableUserIds(officeId, permission);
+ NotificationData notificationData = new
NotificationData().setObjectType(objectType).setObjectId(objectIdentifier)
+
.setAction(eventType).setActorId(appUserId).setContent(notificationContent).setRead(false).setSystemGenerated(false)
+
.setTenantIdentifier(tenantIdentifier).setOfficeId(officeId).setUserIds(userIds);
+ try {
+
notificationEventPublisher.broadcastNotification(notificationData);
+ } catch (Exception e) {
+ // We want to avoid rethrowing the exception to stop the
business transaction from rolling back
+ log.error("Error while broadcasting notification event", e);
+ }
+ }
+ }
+
+ @Override
+ public boolean hasUnreadUserNotifications(Long appUserId) {
+ if (userNotificationSystemIsEnabled()) {
+ return
notificationReadPlatformService.hasUnreadNotifications(appUserId);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void notifyUsers(NotificationData notificationData) {
+ if (userNotificationSystemIsEnabled()) {
+ Long appUserId = notificationData.getActorId();
+
+ Set<Long> userIds = notificationData.getUserIds();
+
+ if (notificationData.getOfficeId() != null) {
+ List<Long> tempUserIds = new ArrayList<>(userIds);
+ for (Long userId : tempUserIds) {
+ AppUser appUser =
appUserRepository.findById(userId).orElseThrow();
+ if (!Objects.equals(appUser.getOffice().getId(),
notificationData.getOfficeId())) {
+ userIds.remove(userId);
+ }
+ }
+ }
+
+ // Don't notify the same user who triggered the event
+ if (userIds.contains(appUserId)) {
+ userIds.remove(appUserId);
+ }
+
+ notificationWritePlatformService.notify(userIds,
notificationData.getObjectType(), notificationData.getObjectId(),
+ notificationData.getAction(),
notificationData.getActorId(), notificationData.getContent(),
+ notificationData.isSystemGenerated());
+ }
+ }
+
+ private boolean userNotificationSystemIsEnabled() {
+ return
fineractProperties.getNotification().getUserNotificationSystem().isEnabled();
+ }
+
+ private Set<Long> getNotifiableUserIds(Long officeId, String permission) {
+ Collection<AppUser> users = appUserRepository.findByOfficeId(officeId);
+ Collection<AppUser> usersWithPermission = users.stream().filter(aU ->
aU.hasAnyPermission(permission, "ALL_FUNCTIONS")).toList();
+ return
usersWithPermission.stream().map(AppUser::getId).collect(toSet());
+ }
+}
diff --git a/fineract-provider/src/main/resources/application.properties
b/fineract-provider/src/main/resources/application.properties
index 714e20715..195496ba0 100644
--- a/fineract-provider/src/main/resources/application.properties
+++ b/fineract-provider/src/main/resources/application.properties
@@ -102,6 +102,8 @@
fineract.report.export.s3.enabled=${FINERACT_REPORT_EXPORT_S3_ENABLED:false}
fineract.jpa.statementLoggingEnabled=${FINERACT_STATEMENT_LOGGING_ENABLED:false}
+fineract.notification.user-notification-system.enabled=${FINERACT_USER_NOTIFICATION_SYSTEM_ENABLED:true}
+
# Logging pattern for the console
logging.pattern.console=${CONSOLE_LOG_PATTERN:%clr(%d{yyyy-MM-dd
HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta}
%clr(%replace([%X{correlationId}]){'\\[\\]', ''}) %clr(---){faint}
%clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint}
%m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}}