From b502ad0c2d5d62a20e7a994c08e87518d70d7e58 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Tue, 26 Mar 2024 10:28:21 +0100 Subject: [PATCH] in progress notification plugin --- notifications-plugins/README.md | 70 +++++++++++ .../NotificationEventsSubscribedConfig.java | 1 + .../notifications/NotificationsPlugin.java | 55 ++++---- .../cms/notifications/config/Notify.java | 12 -- .../config/SubscribeNotificationEvent.java | 56 --------- .../GeoportalServiceAccount.java | 51 ++++++++ .../serviceaccount/IAMClientCredentials.java | 90 ++++++++++++++ .../IAMClientCredentialsReader.java | 82 ++++++++++++ .../manage/ManageDoActionNotification.java | 35 ++++-- .../cms/notifications/manage/NotifyUsers.java | 108 ++++++++-------- .../test/java/CatalogueBindingPluginTest.java | 117 ++++++++++++------ .../src/test/java/StringReplacerTest.java | 4 +- 12 files changed, 484 insertions(+), 197 deletions(-) create mode 100644 notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/serviceaccount/GeoportalServiceAccount.java create mode 100644 notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/serviceaccount/IAMClientCredentials.java create mode 100644 notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/serviceaccount/IAMClientCredentialsReader.java diff --git a/notifications-plugins/README.md b/notifications-plugins/README.md index 6768c33..d5f3648 100644 --- a/notifications-plugins/README.md +++ b/notifications-plugins/README.md @@ -16,6 +16,76 @@ This module is expected to contain plugin definitions for the generations of not ## Documentation [gCube CMS Suite](../) parent module containing references, documentation, guides ad utilities. +This plugin requires a configuration of type: + +```json +{ + "subscribeNotifications": [ + { + "event": "EVENT_NAME", + "notificationFor": [ + { + "roles": [ + "USER_ROLE" + ], + "when": [ + { + "target_phase": [ + "TARGET_PHASE" + ], + "last_invoked_step": LAST_INVOKED_STEP_1, + "notify": [ + { + "type": "NOTIFICATION_TYPE", + "send": "true/false", + "placeholder_msg": "PLACEHOLDER_MESSAGE_1", + "export_as_pdf": { + "placeholder_msg": "Export as PDF placeholder", + "export": true + } + } + ] + }, + { + "target_phase": [ + "TARGET_PHASE" + ], + "last_invoked_step": LAST_INVOKED_STEP_2, + "notify": [ + { + "type": "NOTIFICATION_TYPE", + "send": "true/false", + "placeholder_msg": "PLACEHOLDER_MESSAGE_2", + "export_as_pdf": { + "placeholder_msg": "Export as PDF placeholder", + "export": true + } + } + ] + } + ] + } + ] + } + ], + "enabled":true/false, + "link_to_notifications_messages" (mandatory): "link to file containg the messages as properties like PLACEHOLDER_MESSAGE_{N} = value" +} +``` + +Where: + +* `enabled`: (optional) can be true/false. Default is true. It enables or not the plugin. +* `link_to_notifications_messages`: it is the URL to Notifications Messages file with placeholder values. A property file like PLACEHOLDER_MESSAGE_{N} = value + +and + +* `EVENT_NAME` (mandatory) can be: `PROJECT_CREATED`, `PROJECT_UPDATED`, `PROJECT_DELETED`, `LIFECYCLE_STEP_PERFORMED`. +* `USER_ROLE` (mandatory) can be: `Data-Manager`, `Data-Editor`, `Member"`, `Item_Creator`, `Any`; +* `TARGET_PHASE` (mandatory) can be: `DRAFT`, `Pending Approval`, `Published`, `Any`; +* `LAST_INVOKED_STEP` (optional) can be: `SUBMIT-FOR-REVIEW​`, `APPROVE-SUBMITTED`, `REJECT-DRAFT​`, `UNPUBLISH`; +* `NOTIFICATION_TYPE` (mandatory) can be: `USER_POST`, `VRE_POST`, `EMAIL`; + ## Change log diff --git a/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/NotificationEventsSubscribedConfig.java b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/NotificationEventsSubscribedConfig.java index b8b47c4..7683137 100644 --- a/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/NotificationEventsSubscribedConfig.java +++ b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/NotificationEventsSubscribedConfig.java @@ -14,4 +14,5 @@ public class NotificationEventsSubscribedConfig { UseCaseDescriptor ucd; List listNotificationEventSubscribed; String linkToNotificationsMessages; + boolean enabled = true; } diff --git a/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/NotificationsPlugin.java b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/NotificationsPlugin.java index 4a3eaa8..9f794c2 100644 --- a/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/NotificationsPlugin.java +++ b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/NotificationsPlugin.java @@ -316,7 +316,9 @@ public class NotificationsPlugin extends AbstractPlugin implements EventListener notificationMapPerContext .setListNotificationEventSubscribed(listNotificationEventsSubscribedPerUCD); String linkToMessages = profileConfiguration.get("link_to_notifications_messages", String.class); + Boolean enabledNotifications = profileConfiguration.get("enabled", Boolean.class); notificationMapPerContext.setLinkToNotificationsMessages(linkToMessages); + notificationMapPerContext.setEnabled(enabledNotifications); } setNotificationBindingMapPerContext(context, useCaseDescriptor, notificationMapPerContext); @@ -352,7 +354,7 @@ public class NotificationsPlugin extends AbstractPlugin implements EventListener @Override public void doAction(ItemObserved itemObserved) { log.debug("doAction called..."); - + boolean isSubscribedEvent = checkIfSubscribedEvent(itemObserved); log.info("Is the event {} subscribed in notification plugin configured in the UCD: {} ", @@ -366,35 +368,34 @@ public class NotificationsPlugin extends AbstractPlugin implements EventListener NotificationEventsSubscribedConfig subscribedConfig = notificationMapPerContext .get(itemObserved.getUCD_Id()); - String linkToFileWithMessages = subscribedConfig.getLinkToNotificationsMessages(); - List list = subscribedConfig.getListNotificationEventSubscribed(); + boolean subscribeNotificationsEnabled = subscribedConfig.isEnabled(); - //Filtering list of SubscribeNotificationEvent for itemObserved Event - List filterList = list.stream() - .filter(sne -> sne.getEvent().equals(itemObserved.getEvent())).collect(Collectors.toList()); + log.info("subscribeNotifications enabled: {}", subscribeNotificationsEnabled); + + if (subscribeNotificationsEnabled) { + + String linkToFileWithMessages = subscribedConfig.getLinkToNotificationsMessages(); + List list = subscribedConfig.getListNotificationEventSubscribed(); + + // Filtering list of SubscribeNotificationEvent for itemObserved Event + List filterList = list.stream() + .filter(sne -> sne.getEvent().equals(itemObserved.getEvent())).collect(Collectors.toList()); + + log.debug(linkToFileWithMessages); + NMessagesPlaceholdersSubstitutorUtil nMPlaceholdersSUtil = null; + try { + nMPlaceholdersSUtil = new NMessagesPlaceholdersSubstitutorUtil(linkToFileWithMessages); + } catch (IOException e) { + log.error("Error instancing the {}. Please check the URL {}. Returning!!", + NMessagesPlaceholdersSubstitutorUtil.class.getSimpleName(), linkToFileWithMessages); + return; + } + + ManageDoActionNotification mdoact = new ManageDoActionNotification(itemObserved, nMPlaceholdersSUtil, + filterList); + mdoact.manage(); - log.debug(linkToFileWithMessages); - NMessagesPlaceholdersSubstitutorUtil nMPlaceholdersSUtil = null; - try { - nMPlaceholdersSUtil = new NMessagesPlaceholdersSubstitutorUtil(linkToFileWithMessages); - } catch (IOException e) { - log.error("Error instancing the {}. Please check the URL {}. Returning!!", NMessagesPlaceholdersSubstitutorUtil.class.getSimpleName(), linkToFileWithMessages); - return; } - - ManageDoActionNotification mdoact = new ManageDoActionNotification(itemObserved, nMPlaceholdersSUtil, filterList); - mdoact.manage(); - -// for (SubscribeNotificationEvent subscribeNotificationEvent : filterList) { -// List listNotificationFor = subscribeNotificationEvent.getNotificationFor(); -// -// UserUtils.getCurrent().getRoles(); -// -// for (NotificationFor notificationFor : listNotificationFor) { -// notificationFor.getRoles(); -// } -// } - } } diff --git a/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/Notify.java b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/Notify.java index 8768a6f..e30e857 100644 --- a/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/Notify.java +++ b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/Notify.java @@ -6,18 +6,6 @@ import org.gcube.com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; -/** - * Instantiates a new notify. - * - * - { - "type": "NOTIFICATION_TYPE", - "send": "true/false", - "placeholder_msg": "PLACEHOLDER_MESSAGE_1", - "export_as_pdf": "ExportAsPDF" - } - * - */ @Data @JsonIgnoreProperties(ignoreUnknown = true) public class Notify { diff --git a/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/SubscribeNotificationEvent.java b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/SubscribeNotificationEvent.java index 722e878..cbd2a59 100644 --- a/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/SubscribeNotificationEvent.java +++ b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/SubscribeNotificationEvent.java @@ -7,62 +7,6 @@ import org.gcube.com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Data; -/** - * - * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it - * - * Jan 30, 2024 - */ - -/** - * Instantiates a new subscribe notification config. - * -{ - "subscribeNotifications": [ - { - "event": "EVENT_NAME", - "notificationFor": [ - { - "roles": [ - "USER_ROLE" - ], - "when": [ - { - "target_phase": [ - "TARGET_PHASE" - ], - "notify": [ - { - "type": "NOTIFICATION_TYPE", - "send": "true/false", - "attach_pdf_document": "true/false", - "message": "PLACEHOLDER_MESSAGE_1" - } - ] - }, - { - "target_phase": [ - "TARGET_PHASE" - ], - "notify": [ - { - "type": "NOTIFICATION_TYPE", - "send": "true/false", - "attach_pdf_document": "true/false", - "message": "PLACEHOLDER_MESSAGE_2" - } - ] - } - ] - } - ] - } - ], - "link_to_messages": "link to file containing the messages as properties like ID_MESSAGE_{N} = value" -} - * - */ - @Data @JsonIgnoreProperties(ignoreUnknown = true) public class SubscribeNotificationEvent { diff --git a/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/serviceaccount/GeoportalServiceAccount.java b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/serviceaccount/GeoportalServiceAccount.java new file mode 100644 index 0000000..4e95c72 --- /dev/null +++ b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/serviceaccount/GeoportalServiceAccount.java @@ -0,0 +1,51 @@ +package org.gcube.application.cms.notifications.config.serviceaccount; + +import java.util.AbstractMap.SimpleEntry; +import java.util.Map.Entry; + +import javax.ws.rs.InternalServerErrorException; + +import org.gcube.common.authorization.utils.manager.SecretManagerProvider; +import org.gcube.common.authorization.utils.secret.JWTSecret; +import org.gcube.common.authorization.utils.secret.Secret; +import org.gcube.common.keycloak.KeycloakClientFactory; +import org.gcube.common.keycloak.model.TokenResponse; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class GeoportalServiceAccount { + + //geoportal service account config property file + protected static final String CLIENT_ID_PROPERTY_NAME = "clientId"; + + private static String clientId = "geoportal"; + + private static Entry getClientIdAndClientSecret(String context) { + try { + IAMClientCredentials credentials = IAMClientCredentialsReader.getCredentials(); + + clientId = credentials.getClientId()==null?clientId:credentials.getClientId(); + String clientSecret = credentials.getClientSecret(); + SimpleEntry entry = new SimpleEntry(clientId, clientSecret); + return entry; + } catch(Exception e) { + throw new InternalServerErrorException( + "Unable to retrieve Application Token for context " + SecretManagerProvider.instance.get().getContext(), e); + } + } + + private static TokenResponse getJWTAccessToken() throws Exception { + String context = SecretManagerProvider.instance.get().getContext(); + Entry entry = getClientIdAndClientSecret(context); + TokenResponse tr = KeycloakClientFactory.newInstance().queryUMAToken(context, entry.getKey(), entry.getValue(), context, null); + return tr; + } + + public static Secret getGeoportalSecret() throws Exception { + TokenResponse tr = getJWTAccessToken(); + Secret secret = new JWTSecret(tr.getAccessToken()); + return secret; + } + +} diff --git a/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/serviceaccount/IAMClientCredentials.java b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/serviceaccount/IAMClientCredentials.java new file mode 100644 index 0000000..fad80f5 --- /dev/null +++ b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/serviceaccount/IAMClientCredentials.java @@ -0,0 +1,90 @@ +package org.gcube.application.cms.notifications.config.serviceaccount; + +import java.io.Serializable; + +/** + * The Class IAMClientCredentials. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Sep 23, 2021 + */ +public class IAMClientCredentials implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 7242909633989611318L; + private String clientId; + private String clientSecret; + + /** + * Instantiates a new IAM client credentials. + */ + public IAMClientCredentials() { + } + + /** + * Instantiates a new IAM client credentials. + * + * @param clientId the client id + * @param clientSecret the client secret + */ + public IAMClientCredentials(String clientId, String clientSecret) { + this.clientId = clientId; + this.clientSecret = clientSecret; + } + + /** + * Gets the client id. + * + * @return the client id + */ + public String getClientId() { + return clientId; + } + + /** + * Gets the client secret. + * + * @return the client secret + */ + public String getClientSecret() { + return clientSecret; + } + + /** + * Sets the client id. + * + * @param clientId the new client id + */ + public void setClientId(String clientId) { + this.clientId = clientId; + } + + /** + * Sets the client secret. + * + * @param clientSecret the new client secret + */ + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("IAMClientCredentials [clientId="); + builder.append(clientId); + builder.append(", clientSecret="); + builder.append(clientSecret != null ? clientSecret.subSequence(0, 5) + "_MASKED_SECRET" : null); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/serviceaccount/IAMClientCredentialsReader.java b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/serviceaccount/IAMClientCredentialsReader.java new file mode 100644 index 0000000..a35520d --- /dev/null +++ b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/config/serviceaccount/IAMClientCredentialsReader.java @@ -0,0 +1,82 @@ +package org.gcube.application.cms.notifications.config.serviceaccount; + +import static org.gcube.resources.discovery.icclient.ICFactory.clientFor; +import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; + +import java.util.Collection; +import java.util.List; + +import org.gcube.common.authorization.utils.manager.SecretManagerProvider; +import org.gcube.common.encryption.StringEncrypter; +import org.gcube.common.resources.gcore.ServiceEndpoint; +import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; +import org.gcube.resources.discovery.client.api.DiscoveryClient; +import org.gcube.resources.discovery.client.queries.api.SimpleQuery; + +import lombok.extern.slf4j.Slf4j; + +/** + * The Class GNABaseMapsResourceReader. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Sep 23, 2021 + */ +@Slf4j +public class IAMClientCredentialsReader { + + private static final String SE_PROFILE_NAME = "geoportal"; + private static final String SE_CATEGORY_NAME = "SystemClient"; + + /** + * Gets the credentials. + * + * @return the credentials + * @throws Exception the exception + */ + public static IAMClientCredentials getCredentials() throws Exception { + + String currentContext = SecretManagerProvider.instance.get().getContext(); + + log.info("Searching SE in the scope: " + currentContext + " with profile name: " + SE_PROFILE_NAME + + " and category name: " + SE_CATEGORY_NAME); + + SimpleQuery query = queryFor(ServiceEndpoint.class); + query.addCondition("$resource/Profile/Name/text() eq '" + SE_PROFILE_NAME + "'"); + query.addCondition("$resource/Profile/Category/text() eq '" + SE_CATEGORY_NAME + "'"); + + DiscoveryClient client = clientFor(ServiceEndpoint.class); + List resources = client.submit(query); + + if (resources.size() > 0) + log.info("The query returned " + resources.size() + " ServiceEndpoint/s"); + else + throw new RuntimeException("ServiceEndpoint not found. Searching for profile name '" + SE_PROFILE_NAME + + "' and category name '" + SE_CATEGORY_NAME + "' in the scope: " + currentContext); + + ServiceEndpoint se = resources.get(0); + Collection theAccessPoints = se.profile().accessPoints().asCollection(); + String clientId = null; + String secredPwd = null; + for (AccessPoint accessPoint : theAccessPoints) { + clientId = accessPoint.username(); + secredPwd = accessPoint.password(); + log.debug("Found clientId: " + clientId + " and encrypted secret: " + secredPwd); + // decrypting the pwd + try { + if (secredPwd != null) { + secredPwd = StringEncrypter.getEncrypter().decrypt(secredPwd); + log.debug("Secret decrypted is: " + secredPwd.substring(0, secredPwd.length() / 2) + + "_MASKED_TOKEN_"); + } + } catch (Exception e) { + throw new RuntimeException("Error on decrypting the pwd: ", e); + } + } + + log.info("Returning keycloack credentials for SE {} read from SE", SE_PROFILE_NAME); + return new IAMClientCredentials(clientId, secredPwd); + + } + +} diff --git a/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/manage/ManageDoActionNotification.java b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/manage/ManageDoActionNotification.java index cbf6aa0..b12e18c 100644 --- a/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/manage/ManageDoActionNotification.java +++ b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/manage/ManageDoActionNotification.java @@ -87,7 +87,7 @@ public class ManageDoActionNotification { String lastInvokedStep = lInfo.getLastInvokedStep(); log.debug("ItemObserved phase is: {}, lastInvokedStep is: {}", itemPhase, lastInvokedStep); - //final SecretManager cm = SecretManagerProvider.instance.get(); + // final SecretManager cm = SecretManagerProvider.instance.get(); for (final NotificationFor notificationFor : listNotificationFor) { // Filtering notifications on 'phase' and 'lastInvokedStep' according to item @@ -100,16 +100,17 @@ public class ManageDoActionNotification { if (notificationsCompliantToPhase != null && notificationsCompliantToPhase.size() > 0) { // GET LIST USER COMPLIANT TO ROLES - List notifyUsers = getListUserCompliantToRoles(notificationFor, itemObserved, true); + List notifyUsers = getListUserCompliantToRoles(notificationFor, itemObserved, false); final SocialClients socialClients = new SocialClients(); - CatalogueEventType catalogueEventType = MappingToCatalogue.toCatalogueEventType(itemPhase, lastInvokedStep); - + CatalogueEventType catalogueEventType = MappingToCatalogue.toCatalogueEventType(itemPhase, + lastInvokedStep); + if (notifyUsers.size() > 0) { log.info("Users compliant to role are: {}", notifyUsers.size()); if (log.isDebugEnabled()) { notifyUsers.stream().forEach(u -> log.debug("notifying user: " + u)); } - + try { NotifyUsers mnu = new NotifyUsers(socialClients, notificationsCompliantToPhase, nMPlaceholdersS, notifyUsers, catalogueEventType); @@ -125,8 +126,9 @@ public class ManageDoActionNotification { } public static List matchNotificationsAccordingItemStatus(NotificationFor notificationFor, - String itemPhase, String lastInvokedStep) { - log.info("Filtering notifications according to phase: {}, lastInvokedStep: {}", itemPhase, lastInvokedStep); + final String itemPhase, final String lastInvokedStep) { + log.info("Filtering notifications according to item status [phase: {}, lastInvokedStep: {}]", itemPhase, + lastInvokedStep); List filteredList = new ArrayList(); @@ -136,20 +138,29 @@ public class ManageDoActionNotification { notificationWhen.getTarget_phase(), notificationWhen.getLast_invoked_step()); if (notificationWhen.getTarget_phase().contains(itemPhase) || notificationWhen.getTarget_phase() .contains(NotificationGenericConstants.CUSTOM_TARGET_PHASE.Any.name())) { - if (notificationWhen.getLast_invoked_step() == null) { + log.debug("target phase: {} - matched", itemPhase); + + String lastInvokedStepConfig = notificationWhen.getLast_invoked_step().trim(); + log.debug("last_invoked_step read in config is {}", lastInvokedStepConfig); + if (lastInvokedStepConfig == null) { + log.debug("last_invoked_step is null or empty - {} matched", lastInvokedStep); // no filtering on lastInvokedStep filteredList.add(notificationWhen); - - } else if (notificationWhen.getLast_invoked_step().compareToIgnoreCase(lastInvokedStep) == 0) { + }else if (lastInvokedStepConfig.contentEquals(lastInvokedStep)) { + log.debug("last_invoked_step: {} - matched", lastInvokedStep); // matching the lastInvokedStep filteredList.add(notificationWhen); + } else { + log.debug("last_invoked_step {} - NOT matched", lastInvokedStep); } + } else { + log.debug("target phase: {} - NOT matched", itemPhase); } } - log.info("returning filtered list with {} object {}. If 0 returned no notifications is sent", filteredList.size(), - NotificationWhen.class.getSimpleName()); + log.info("returning filtered list with {} object {} (if 0 returned no notifications is sent)", + filteredList.size(), NotificationWhen.class.getSimpleName()); return filteredList; } diff --git a/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/manage/NotifyUsers.java b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/manage/NotifyUsers.java index 295c881..81e5a3e 100644 --- a/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/manage/NotifyUsers.java +++ b/notifications-plugins/src/main/java/org/gcube/application/cms/notifications/manage/NotifyUsers.java @@ -7,11 +7,13 @@ import java.util.stream.Collectors; import org.gcube.application.cms.notifications.config.NotificationWhen; import org.gcube.application.cms.notifications.config.Notify; +import org.gcube.application.cms.notifications.config.serviceaccount.GeoportalServiceAccount; import org.gcube.application.cms.notifications.social.SocialClients; import org.gcube.application.cms.notifications.substitutor.NMessagesPlaceholdersSubstitutorUtil; import org.gcube.application.geoportal.common.model.document.accounting.User; import org.gcube.common.authorization.utils.manager.SecretManager; import org.gcube.common.authorization.utils.manager.SecretManagerProvider; +import org.gcube.common.authorization.utils.secret.Secret; import org.gcube.portal.databook.shared.Post; import org.gcube.social_networking.social_networking_client_library.NotificationClient; import org.gcube.social_networking.socialnetworking.model.beans.PostInputBean; @@ -30,7 +32,8 @@ public class NotifyUsers { private CatalogueEventType catalogueEventType; public NotifyUsers(SocialClients socialClients, List listWhen, - NMessagesPlaceholdersSubstitutorUtil nMPlaceholdersSUtil, List recipientUsers, CatalogueEventType catalogueEventType) { + NMessagesPlaceholdersSubstitutorUtil nMPlaceholdersSUtil, List recipientUsers, + CatalogueEventType catalogueEventType) { this.socialClients = socialClients; this.listNotificationWhen = listWhen; this.recipientUsers = recipientUsers; @@ -38,7 +41,6 @@ public class NotifyUsers { this.catalogueEventType = catalogueEventType; } - public void sendNotification() throws Exception { log.info("send notification..."); List listNotifies = toNotify(); @@ -51,14 +53,14 @@ public class NotifyUsers { log.debug("Building message..."); String subject = "Message"; String body = null; - + subject = nMPlaceholdersSUtil.replacePlaceholder(notify.getPlaceholder_title()); body = nMPlaceholdersSUtil.replacePlaceholder(notify.getPlaceholder_msg()); - + log.debug("subject: {}", subject); log.debug("body: {}", body); log.info("Sending message to users: {}", recipientUsers); - + postMessage(subject, body, catalogueEventType); } @@ -80,7 +82,7 @@ public class NotifyUsers { } } - + private List toNotify() { List listNotifies = new ArrayList(); for (NotificationWhen notificationWhen : listNotificationWhen) { @@ -89,77 +91,83 @@ public class NotifyUsers { } return listNotifies; } - - protected void postMessage(String subject, String bodyMessage, CatalogueEventType catalogueEventType) throws Exception { + + protected void postMessage(String subject, String bodyMessage, CatalogueEventType catalogueEventType) + throws Exception { CatalogueEvent catalogueEvent = getCatalogueEvent(subject, bodyMessage); SecretManager secretManager = SecretManagerProvider.instance.get(); - - //GET geoportal SECRET - -// Secret secret = Constants.getCatalogueSecret(); -// if(notificationSentByGCat) { -// secretManager.startSession(secret); -// } -// try { -// sendNotification(catalogueEvent); -// }finally { -// if(notificationSentByGCat) { -// secretManager.endSession(); -// } -// } - - //sendNotification(catalogueEvent); + try { + Secret geoportalSecret = GeoportalServiceAccount.getGeoportalSecret(); + secretManager.startSession(geoportalSecret); + sendNotification(catalogueEvent); + } catch (Exception e) { + log.error("Error while sending notification", e); + } finally { + if (secretManager != null) { + secretManager.endSession(); + } + } } - + + protected void sendNotification(CatalogueEvent catalogueEvent) throws Exception { + + try { + Thread thread = new Thread() { + public void run() { + try { + log.debug("{} is going to send the following notification {}", + SecretManagerProvider.instance.get().getUser().getUsername(), catalogueEvent); + NotificationClient nc = socialClients.getNotificationClient(); + nc.sendCatalogueEvent(catalogueEvent); + } catch (Exception e) { + log.error("Error while sending notification from thread", e); + } finally { + + } + } + }; + // thread.run(); + thread.start(); + } catch (Exception e) { + log.error("Error while sending notification", e); + } + +// log.debug("{} is going to send the following notification {}", SecretManagerProvider.instance.get().getUser().getUsername(), catalogueEvent); +// NotificationClient nc = socialClients.getNotificationClient(); +// nc.sendCatalogueEvent(catalogueEvent); + } + protected CatalogueEvent getCatalogueEvent(String subject, String bodyMessage) throws Exception { CatalogueEvent catalogueEvent = new CatalogueEvent(); catalogueEvent.setType(catalogueEventType); catalogueEvent.setNotifyText(bodyMessage); catalogueEvent.setItemId(subject); String itemURL = nMPlaceholdersSUtil.getPlaceholderMapValues().getGisLink(); - if(itemURL!=null) { + if (itemURL != null) { catalogueEvent.setItemURL(new URL(itemURL)); } - + // Adding recipient users String[] usersToNotify = recipientUsers.stream().map(u -> u.getUsername()).toArray(String[]::new); catalogueEvent.setIdsToNotify(usersToNotify); catalogueEvent.setIdsAsGroup(false); - + return catalogueEvent; } - - protected void sendNotification(CatalogueEvent catalogueEvent) throws Exception { - Thread thread = new Thread() { - public void run() { - try { - log.trace("{} is going to send the following notification {}", SecretManagerProvider.instance.get().getUser().getUsername(), catalogueEvent); - NotificationClient nc = socialClients.getNotificationClient(); - nc.sendCatalogueEvent(catalogueEvent); - } catch(Exception e) { - log.error("Error while sending notification.", e); - } - } - }; - // thread.run(); - thread.start(); - } - - protected CatalogueEvent toCatalogueEvent(CatalogueEventType catalogueEventType, String messageString, String subject, String itemURL, List users) throws Exception { + protected CatalogueEvent toCatalogueEvent(CatalogueEventType catalogueEventType, String messageString, + String subject, String itemURL, List users) throws Exception { CatalogueEvent catalogueEvent = new CatalogueEvent(); catalogueEvent.setType(catalogueEventType); catalogueEvent.setNotifyText(messageString); catalogueEvent.setItemId(subject); - if(itemURL!=null) { + if (itemURL != null) { catalogueEvent.setItemURL(new URL(itemURL)); } catalogueEvent.setIdsToNotify(users.toArray(new String[users.size()])); catalogueEvent.setIdsAsGroup(false); - + return catalogueEvent; } - - } diff --git a/notifications-plugins/src/test/java/CatalogueBindingPluginTest.java b/notifications-plugins/src/test/java/CatalogueBindingPluginTest.java index e2f6c45..ad345e8 100644 --- a/notifications-plugins/src/test/java/CatalogueBindingPluginTest.java +++ b/notifications-plugins/src/test/java/CatalogueBindingPluginTest.java @@ -75,11 +75,9 @@ public class CatalogueBindingPluginTest extends BasicPluginTest { } - @Test - public void checkNotifications() { + //@Test + public void checkNotifications_LIFECYCLE_STEP_PERFORMED() { org.junit.Assume.assumeTrue(GCubeTest.isTestInfrastructureEnabled()); - // NotificationsPlugin plugin = (NotificationsPlugin) - // plugins.get(NotificationsPlugin.DESCRIPTOR.getId()); UseCaseDescriptor descriptor = TestProfiles.profiles.get("profiledConcessioni"); NotificationEventsSubscribedConfig notificationEventsSubs; @@ -93,7 +91,48 @@ public class CatalogueBindingPluginTest extends BasicPluginTest { } catch (Exception e) { e.printStackTrace(); } + + ItemObserved item = mockItemObserverd(); + + EventManager.Event event = Event.LIFECYCLE_STEP_PERFORMED; + item.setEvent(event); + + LifecycleInformation lifecycleInfo = item.getProject().getLifecycleInformation(); + //(Pending Approval, "SUBMIT-FOR-REVIEW") +// lifecycleInfo.setPhase("Pending Approval"); +// lifecycleInfo.setLastInvokedStep("SUBMIT-FOR-REVIEW"); + //(DRAFT, REJECT-DRAFT) + lifecycleInfo.setPhase("DRAFT"); + lifecycleInfo.setLastInvokedStep("REJECT-DRAFT"); + + System.out.println("By notifying event " + event + " project " + item.getProjectId()); + EventManager.getInstance().notify(event, item); + } + private void sysOut(SubscribeNotificationEvent subscribeNotificationEvent) { + System.out.println("\n#SubscribeNotificationEvent - Event: " + subscribeNotificationEvent.getEvent()); + List listNotificationFor = subscribeNotificationEvent.getNotificationFor(); + for (NotificationFor notificationFor : listNotificationFor) { + System.out.println("\tNotificationFor - roles: " + notificationFor.getRoles()); + for (NotificationWhen notificationWhen : notificationFor.getWhen()) { + System.out.println("\t\tNotificationWhen - Target_phase: " + notificationWhen.getTarget_phase() + + ", Last_invoked_step: " + notificationWhen.getLast_invoked_step()); + for (Notify notify : notificationWhen.getNotify()) { + System.out.println("\t\t\tNotify type : " + notify.getType()); + System.out.println("\t\t\tNotify send : " + notify.getSend()); + System.out.println("\t\t\tNotify placeholder_message : " + notify.getPlaceholder_msg()); + if (notify.getExport_as_pdf() != null) { + System.out.println("\t\t\t\tExport as PDF : " + notify.getExport_as_pdf()); + } + } + } + } + } + + private static ItemObserved mockItemObserverd() { + + UseCaseDescriptor descriptor = TestProfiles.profiles.get("profiledConcessioni"); + // notifying the Event.PROJECT_CREATED; ItemObserved item = new ItemObserved(); EventManager.Event event = Event.LIFECYCLE_STEP_PERFORMED; @@ -119,52 +158,51 @@ public class CatalogueBindingPluginTest extends BasicPluginTest { testProject.setTheDocument(theDocument); LifecycleInformation lifecycleInfo = new LifecycleInformation(); - lifecycleInfo.setPhase("Pending Approval"); - lifecycleInfo.setLastInvokedStep("SUBMIT-FOR-REVIEW"); + //Pending Approval, "SUBMIT-FOR-REVIEW" +// lifecycleInfo.setPhase("Pending Approval"); +// lifecycleInfo.setLastInvokedStep("SUBMIT-FOR-REVIEW"); + + lifecycleInfo.setPhase("DRAFT"); + lifecycleInfo.setLastInvokedStep("REJECT-DRAFT"); + testProject.setLifecycleInformation(lifecycleInfo); - item.setProject(testProject); - System.out.println("By notifying event " + event + " project " + item.getProjectId()); - EventManager.getInstance().notify(event, item); - - } - - private void sysOut(SubscribeNotificationEvent subscribeNotificationEvent) { - System.out.println("\n#SubscribeNotificationEvent - Event: " + subscribeNotificationEvent.getEvent()); - List listNotificationFor = subscribeNotificationEvent.getNotificationFor(); - for (NotificationFor notificationFor : listNotificationFor) { - System.out.println("\tNotificationFor - roles: " + notificationFor.getRoles()); - for (NotificationWhen notificationWhen : notificationFor.getWhen()) { - System.out.println("\t\tNotificationWhen - Target_phase: " + notificationWhen.getTarget_phase() - + ", Last_invoked_step: " + notificationWhen.getLast_invoked_step()); - for (Notify notify : notificationWhen.getNotify()) { - System.out.println("\t\t\tNotify type : " + notify.getType()); - System.out.println("\t\t\tNotify send : " + notify.getSend()); - System.out.println("\t\t\tNotify placeholder_message : " + notify.getPlaceholder_msg()); - if (notify.getExport_as_pdf() != null) { - System.out.println("\t\t\t\tExport as PDF : " + notify.getExport_as_pdf()); - } - } - } - } + + return item; } //@Test public void matchingNotificationTest() { org.junit.Assume.assumeTrue(GCubeTest.isTestInfrastructureEnabled()); - String itemPhase = "Pending Approval"; - String lastInvokedStep = "SUBMIT-FOR-REVIEW"; +// String itemPhase = "Pending Approval"; +// String lastInvokedStep = "SUBMIT-FOR-REVIEW"; + String itemPhase = "DRAFT"; + String lastInvokedStep = "REJECT-DRAFT"; + + UseCaseDescriptor descriptor = TestProfiles.profiles.get("profiledConcessioni"); + NotificationEventsSubscribedConfig notificationEventsSubs; List listWhen = new ArrayList(); + try { + System.out.println(NotificationEventsSubscribedConfig.class.getSimpleName() + ": "); + notificationEventsSubs = plugin.readNotificationsSubscribedFromConfigurationInTheUCD(descriptor); + List events = notificationEventsSubs.getListNotificationEventSubscribed(); + for (SubscribeNotificationEvent subscribeNotificationEvent : events) { + for (NotificationFor notificationFor : subscribeNotificationEvent.getNotificationFor()) { + listWhen.addAll(ManageDoActionNotification.matchNotificationsAccordingItemStatus(notificationFor, itemPhase, lastInvokedStep)); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + /* SubscribeNotificationEvent sne = mockSubscribeNotificationEvent(); for (NotificationFor notificationFor : sne.getNotificationFor()) { listWhen.addAll(ManageDoActionNotification.matchNotificationsAccordingItemStatus(notificationFor, itemPhase, lastInvokedStep)); } - + */ System.out.println("Filtered notifications: "+listWhen); - - } // @Test @@ -201,11 +239,16 @@ public class CatalogueBindingPluginTest extends BasicPluginTest { NotificationFor notificatioFor = new NotificationFor(); notificatioFor.setRoles(Arrays.asList("Data-Manager")); + //Pending Approval, "SUBMIT-FOR-REVIEW" List listWhen = new ArrayList(); NotificationWhen notificationWhen = new NotificationWhen(); + notificationWhen.setTarget_phase(Arrays.asList("Pending Approval")); notificationWhen.setLast_invoked_step("SUBMIT-FOR-REVIEW"); - + +// notificationWhen.setTarget_phase(Arrays.asList("DRAFT")); +// notificationWhen.setLast_invoked_step("REJECT-DRAFT"); + Notify notify = new Notify(); notify.setType(NOTIFICATION_TYPE.EMAIL); notify.setSend(true); @@ -221,7 +264,7 @@ public class CatalogueBindingPluginTest extends BasicPluginTest { notificatioFor.setWhen(listWhen); listNotificationFor.add(notificatioFor); - + sne.setNotificationFor(listNotificationFor); return sne; diff --git a/notifications-plugins/src/test/java/StringReplacerTest.java b/notifications-plugins/src/test/java/StringReplacerTest.java index 497afc2..c1d4439 100644 --- a/notifications-plugins/src/test/java/StringReplacerTest.java +++ b/notifications-plugins/src/test/java/StringReplacerTest.java @@ -2,9 +2,7 @@ import java.io.BufferedInputStream; import java.io.IOException; import java.net.URL; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Properties; import org.apache.commons.text.StringSubstitutor; @@ -31,7 +29,7 @@ public class StringReplacerTest { public static String FILE_URL = "https://code-repo.d4science.org/gCubeSystem/gcube-cms-suite/raw/branch/event_manager/D4S_UCDs/DEV/devVRE/notifications/Notifications_Messages.properties"; - @Test + //@Test public void checkReplace() { org.junit.Assume.assumeTrue(GCubeTest.isTestInfrastructureEnabled());