diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 8d5217e..341c3a9 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,10 +1,19 @@ + + + + + + + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index 318bc5b..3133d8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v3.0.0-SNAPSHOT] - 2024-04-18 + +- Removed social networking lib dep + ## [v2.5.0] - 2021-06-22 - Feature #21689 Social Mail Servlet to StorageHub migration diff --git a/pom.xml b/pom.xml index 7f44c1c..1ea0ec8 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ org.gcube.portal social-mail-servlet war - 2.5.0 + 3.0.0-SNAPSHOT scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git @@ -37,7 +37,7 @@ org.gcube.distribution maven-portal-bom - 3.6.3 + 3.7.0 pom import @@ -71,15 +71,22 @@ aslsocial provided - - org.gcube.common - storagehub-client-library - org.gcube.portal social-networking-library provided + + org.gcube.social-networking + social-service-client + [2.0.0-SNAPSHOT, 3.0.0) + provided + + + com.squareup.okhttp3 + okhttp + 4.9.3 + org.apache.commons commons-lang3 @@ -109,8 +116,8 @@ com.sun.mail - javax.mail - provided + jakarta.mail + 2.0.1 com.liferay.portal diff --git a/src/main/java/org/gcube/portal/PortalSchedulerService.java b/src/main/java/org/gcube/portal/PortalSchedulerService.java index 52120fc..26ca138 100644 --- a/src/main/java/org/gcube/portal/PortalSchedulerService.java +++ b/src/main/java/org/gcube/portal/PortalSchedulerService.java @@ -17,6 +17,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.gcube.application.framework.core.session.SessionManager; import org.gcube.common.encryption.StringEncrypter; import org.gcube.common.portal.PortalContext; import org.gcube.common.resources.gcore.ServiceEndpoint; @@ -54,6 +55,9 @@ public class PortalSchedulerService extends HttpServlet { private static DatabookStore store; public void init() { + PortalContext context = PortalContext.getConfiguration(); + String scope = "/" + context.getInfrastructureName(); + ScopeProvider.instance.set(scope); store = new DBCassandraAstyanaxImpl(); } @@ -77,7 +81,7 @@ public class PortalSchedulerService extends HttpServlet { pop3Scheduler.scheduleAtFixedRate(new PeriodicTask(store, popAccount, request), 0, pollingInterval, TimeUnit.MINUTES); String portalName = "unknown"; try { - popAccount.getPortalName() ; + portalName = popAccount.getPortalName() ; } catch (NullPointerException e){ _log.warn("Could not read popAccount data portal name", e); diff --git a/src/main/java/org/gcube/portal/socialmail/PeriodicTask.java b/src/main/java/org/gcube/portal/socialmail/PeriodicTask.java index d2681f3..f092c4d 100644 --- a/src/main/java/org/gcube/portal/socialmail/PeriodicTask.java +++ b/src/main/java/org/gcube/portal/socialmail/PeriodicTask.java @@ -2,26 +2,18 @@ package org.gcube.portal.socialmail; import static org.gcube.common.authorization.client.Constants.authorizationService; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; import java.security.GeneralSecurityException; import java.util.ArrayList; -import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Properties; import java.util.UUID; -import javax.mail.Address; -import javax.mail.BodyPart; -import javax.mail.Flags; -import javax.mail.Folder; -import javax.mail.Message; -import javax.mail.MessagingException; -import javax.mail.Multipart; -import javax.mail.NoSuchProviderException; -import javax.mail.Session; -import javax.mail.Store; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeMessage.RecipientType; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringEscapeUtils; @@ -34,14 +26,11 @@ import org.gcube.applicationsupportlayer.social.mailing.AppType; import org.gcube.applicationsupportlayer.social.mailing.SocialMailingUtil; import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingSite; import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingUser; +import org.gcube.common.authorization.library.provider.AccessTokenProvider; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.authorization.library.provider.UserInfo; import org.gcube.common.portal.PortalContext; import org.gcube.common.scope.api.ScopeProvider; -import org.gcube.common.storagehub.client.plugins.AbstractPlugin; -import org.gcube.common.storagehub.client.proxies.MessageManagerClient; -import org.gcube.common.storagehub.model.exceptions.IdNotFoundException; -import org.gcube.common.storagehub.model.exceptions.StorageHubException; import org.gcube.portal.databook.server.DatabookStore; import org.gcube.portal.databook.shared.Comment; import org.gcube.portal.databook.shared.Feed; @@ -54,14 +43,35 @@ import org.gcube.portal.notifications.bean.GenericItemBean; import org.gcube.portal.notifications.thread.CommentNotificationsThread; import org.gcube.portal.notifications.thread.LikeNotificationsThread; import org.gcube.portal.notifications.thread.MessageNotificationsThread; +import org.gcube.social_networking.social_networking_client_library.MessageClient; +import org.gcube.social_networking.socialnetworking.model.beans.MessageInbox; +import org.gcube.social_networking.socialnetworking.model.beans.MessageInputBean; +import org.gcube.social_networking.socialnetworking.model.beans.Recipient; import org.gcube.vomanagement.usermanagement.UserManager; import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager; import org.gcube.vomanagement.usermanagement.model.GCubeUser; +import com.fasterxml.jackson.databind.ObjectMapper; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.sun.mail.util.MailSSLSocketFactory; +import jakarta.mail.Address; +import jakarta.mail.BodyPart; +import jakarta.mail.Flags; +import jakarta.mail.Folder; +import jakarta.mail.Message; +import jakarta.mail.MessagingException; +import jakarta.mail.Multipart; +import jakarta.mail.NoSuchProviderException; +import jakarta.mail.Session; +import jakarta.mail.Store; +import jakarta.mail.internet.InternetAddress; +import jakarta.mail.internet.MimeMessage.RecipientType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.ResponseBody; + /** * * @author Massimiliano Assante, CNR-ISTI @@ -70,6 +80,7 @@ import com.sun.mail.util.MailSSLSocketFactory; public class PeriodicTask implements Runnable { private static final Log _log = LogFactoryUtil.getLog(PeriodicTask.class); private static final String APP_ID_NEWSFEED = "org.gcube.portlets.user.newsfeed.server.NewsServiceImpl"; + private static final String SHUB_MESSAGES_ENDPOINT = "workspace/messages/"; private DatabookStore socialStore; private EmailPopAccount popAccount; @@ -136,6 +147,20 @@ public class PeriodicTask implements Runnable { } return toReturn; } + + private static String generateAuthorizationToken(String username, String scope) { + List userRoles = new ArrayList<>(); + userRoles.add(DEFAULT_ROLE); + String token; + try { + token = authorizationService().generateUserToken(new UserInfo(username, userRoles), scope); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + return token; + } + private final static String DEFAULT_ROLE = "OrganizationMember"; private static void setAuthorizationToken(ASLSession session) throws Exception { @@ -250,6 +275,16 @@ public class PeriodicTask implements Runnable { * @throws Exception */ private void handleMessageReply(String portalName, String messageId, Message message, ASLSession fakeSession) { + + String legacyToken = SecurityTokenProvider.instance.get(); + + _log.info("*****username=" + fakeSession.getUsername()); + _log.info("*****context=" + fakeSession.getScope()); + + legacyToken = generateAuthorizationToken(fakeSession.getUsername(), fakeSession.getScope()); + SecurityTokenProvider.instance.set(legacyToken); + + String subject = ""; String messageText = ""; try { @@ -261,34 +296,23 @@ public class PeriodicTask implements Runnable { _log.debug("Found message reply, subject: " + subject + " body: " + messageText); String newMessageId = null; - List recipientIds = new ArrayList<>(); + ArrayList recipientIds = new ArrayList(); try { String username = fakeSession.getUsername(); - String scope = fakeSession.getScope(); - ScopeProvider.instance.set(scope); - _log.debug("calling service token on scope " + scope); + String context = fakeSession.getScope(); + ScopeProvider.instance.set(context); + _log.debug("calling service token on context " + context); List userRoles = new ArrayList<>(); userRoles.add(DEFAULT_ROLE); fakeSession.setSecurityToken(null); - String token = authorizationService().generateUserToken(new UserInfo(username, userRoles), scope); + String token = authorizationService().generateUserToken(new UserInfo(username, userRoles), context); SecurityTokenProvider.instance.set(token); - MessageManagerClient mmClient = AbstractPlugin.messages().build(); - org.gcube.common.storagehub.model.messages.Message theMessage = null; - try { - theMessage = mmClient.get(messageId); - } - catch (IdNotFoundException e) { - _log.warn("Message with id "+ messageId + " could not be found, trying by name ..."); - List messages = mmClient.getReceivedMessages(); - Collections.reverse(messages); //the messages are returned in chronological order, but the messages we look for is one of the newests - _log.warn("Messages size="+messages.size()); - for(org.gcube.common.storagehub.model.messages.Message msg: messages) { - if (msg.getName().equals(messageId)) { - theMessage = msg; - break; - } - } - } + MessageInbox theMessage = null; + _log.info("Looking for Message with id "+ messageId); + String messagesEndpoint = getStorageHubURLFromContext(context)+SHUB_MESSAGES_ENDPOINT; + theMessage = getMessageWSById(messagesEndpoint, messageId, token); + _log.info("Got Message = " + theMessage.toString()); + if (theMessage != null) { String[] addresses = theMessage.getAddresses(); for (int i = 0; i < addresses.length; i++) { @@ -302,17 +326,20 @@ public class PeriodicTask implements Runnable { recipientIds.remove(fakeSession.getUsername()); _log.debug("Message Recipients:"); + ArrayList recipients = new ArrayList(); for (String rec : recipientIds) { + recipients.add(new Recipient(rec)); _log.debug(rec); } + _log.debug("Constructing reply message"); messageText += getReplyHeaderMessage(sender, originalSentTime, originalText); _log.debug("Trying to send message with subject: " + subject + " to: " + recipientIds.toString()); - newMessageId = mmClient.sendMessage(recipientIds, subject, messageText, new ArrayList()); - } else { - _log.error("Message with id "+ messageId + " could not be found even iterating by name, exiting."); - } + MessageInputBean message2Send = new MessageInputBean(messageText, subject, recipients); + MessageClient messagesClient = new MessageClient(); + newMessageId = messagesClient.writeMessage(message2Send); + } } catch (Exception e) { e.printStackTrace(); @@ -336,6 +363,48 @@ public class PeriodicTask implements Runnable { } } + + /** + * temporary method that get the URL of the Shub based on the context + * @param context + * @return the url + */ + private String getStorageHubURLFromContext(String context) { + String toReturn = ""; + if (context.startsWith("/d4science")) { + toReturn = "https://api.d4science.org/"; + } else if (context.startsWith("/gcube")) { + toReturn = "https://api.dev.d4science.org/"; + } else { + toReturn = "https://api.pre.d4science.org/"; + } + return toReturn; + } + + + /** + * read a message from shub given the id + * @param urlString + * @param token + * @return + * @throws IOException + */ + private static MessageInbox getMessageWSById(String uri, String messageId, String token) throws IOException { + String urlString = uri+messageId; + _log.info("***** getMessageWSById urlString = " + urlString); + OkHttpClient client = new OkHttpClient().newBuilder().build(); + Request request = new Request.Builder() + .url(urlString) + .addHeader("gcube-token", token) + .build(); + ResponseBody responseBody = client.newCall(request).execute().body(); + String json = responseBody.string(); + _log.info("***** getMessageWSById Response = " + json); + ObjectMapper objectMapper = new ObjectMapper(); + MessageInbox theMessage = objectMapper.readValue(json, MessageInbox.class); + return theMessage; + } + private String getReplyHeaderMessage(String senderId, Date date, String message) { List toPass = new ArrayList(); toPass.add(senderId); @@ -376,6 +445,15 @@ public class PeriodicTask implements Runnable { * @throws Exception */ private void handlePostReply(String portalName, String postId, Message message, ASLSession fakeSession) throws Exception { + String token = AccessTokenProvider.instance.get(); + String legacyToken = SecurityTokenProvider.instance.get(); + + _log.info("*****username=" + fakeSession.getUsername()); + _log.info("*****context=" + fakeSession.getScope()); + + legacyToken = generateAuthorizationToken(fakeSession.getUsername(), fakeSession.getScope()); + SecurityTokenProvider.instance.set(legacyToken); + String commentText = extractText(portalName, postId, message); _log.info("Extracted id: " + postId + " text=" + commentText); String escapedCommentText = org.gcube.portal.socialmail.Utils.escapeHtmlAndTransformUrl(commentText); @@ -386,6 +464,7 @@ public class PeriodicTask implements Runnable { likePost(postId, fakeSession); } else { + Comment comment = new Comment(UUID.randomUUID().toString(), fakeSession.getUsername(), new Date(), postId, escapedCommentText, fakeSession.getUserFullName(), fakeSession.getUserAvatarId()); @@ -411,12 +490,21 @@ public class PeriodicTask implements Runnable { * @param fakeSession */ private void likePost(String postId, ASLSession fakeSession) { + + String token = AccessTokenProvider.instance.get(); + String legacyToken = SecurityTokenProvider.instance.get(); + + _log.info("*****username=" + fakeSession.getUsername()); + _log.info("*****context=" + fakeSession.getScope()); + + legacyToken = generateAuthorizationToken(fakeSession.getUsername(), fakeSession.getScope()); + SecurityTokenProvider.instance.set(legacyToken); + if (postId == null || postId.compareTo("") == 0) { _log.warn("Found email with no feedId from " + fakeSession.getUserEmailAddress() + ". Going to trash it"); return; } - Like like = new Like(UUID.randomUUID().toString(), fakeSession.getUsername(), new Date(), postId, fakeSession.getUserFullName(), fakeSession.getUserAvatarId()); @@ -436,7 +524,7 @@ public class PeriodicTask implements Runnable { NotificationsManager nm = new ApplicationNotificationsManager( site, - fakeSession.getScope(), + post.getVreid(), new SocialNetworkingUser(fakeSession.getUsername(), fakeSession.getUserEmailAddress(), fakeSession.getUserFullName(), fakeSession.getUserAvatarId()), APP_ID_NEWSFEED );