updated to work with new portal on OpenStack and social service

This commit is contained in:
Massimiliano Assante 2024-04-22 15:47:29 +02:00
parent f769c3d1ce
commit b8b1e45b64
5 changed files with 166 additions and 54 deletions

View File

@ -1,10 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0"> <?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="social-mail-servlet"> <wb-module deploy-name="social-mail-servlet">
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/> <wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/> <wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<property name="context-root" value="social-mail-servlet"/> <property name="context-root" value="social-mail-servlet"/>
<property name="java-output-path" value="/social-mail-servlet/target/classes"/> <property name="java-output-path" value="/social-mail-servlet/target/classes"/>
</wb-module> </wb-module>
</project-modules> </project-modules>

View File

@ -4,6 +4,10 @@
All notable changes to this project will be documented in this file. 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). 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 ## [v2.5.0] - 2021-06-22
- Feature #21689 Social Mail Servlet to StorageHub migration - Feature #21689 Social Mail Servlet to StorageHub migration

23
pom.xml
View File

@ -12,7 +12,7 @@
<groupId>org.gcube.portal</groupId> <groupId>org.gcube.portal</groupId>
<artifactId>social-mail-servlet</artifactId> <artifactId>social-mail-servlet</artifactId>
<packaging>war</packaging> <packaging>war</packaging>
<version>2.5.0</version> <version>3.0.0-SNAPSHOT</version>
<scm> <scm>
<connection>scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git</connection> <connection>scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git</connection>
<developerConnection>scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git</developerConnection> <developerConnection>scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git</developerConnection>
@ -37,7 +37,7 @@
<dependency> <dependency>
<groupId>org.gcube.distribution</groupId> <groupId>org.gcube.distribution</groupId>
<artifactId>maven-portal-bom</artifactId> <artifactId>maven-portal-bom</artifactId>
<version>3.6.3</version> <version>3.7.0</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
@ -71,15 +71,22 @@
<artifactId>aslsocial</artifactId> <artifactId>aslsocial</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>storagehub-client-library</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.gcube.portal</groupId> <groupId>org.gcube.portal</groupId>
<artifactId>social-networking-library</artifactId> <artifactId>social-networking-library</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.gcube.social-networking</groupId>
<artifactId>social-service-client</artifactId>
<version>[2.0.0-SNAPSHOT, 3.0.0)</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
@ -109,8 +116,8 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.mail</groupId> <groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId> <artifactId>jakarta.mail</artifactId>
<scope>provided</scope> <version>2.0.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.liferay.portal</groupId> <groupId>com.liferay.portal</groupId>

View File

@ -17,6 +17,7 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.gcube.application.framework.core.session.SessionManager;
import org.gcube.common.encryption.StringEncrypter; import org.gcube.common.encryption.StringEncrypter;
import org.gcube.common.portal.PortalContext; import org.gcube.common.portal.PortalContext;
import org.gcube.common.resources.gcore.ServiceEndpoint; import org.gcube.common.resources.gcore.ServiceEndpoint;
@ -54,6 +55,9 @@ public class PortalSchedulerService extends HttpServlet {
private static DatabookStore store; private static DatabookStore store;
public void init() { public void init() {
PortalContext context = PortalContext.getConfiguration();
String scope = "/" + context.getInfrastructureName();
ScopeProvider.instance.set(scope);
store = new DBCassandraAstyanaxImpl(); store = new DBCassandraAstyanaxImpl();
} }
@ -77,7 +81,7 @@ public class PortalSchedulerService extends HttpServlet {
pop3Scheduler.scheduleAtFixedRate(new PeriodicTask(store, popAccount, request), 0, pollingInterval, TimeUnit.MINUTES); pop3Scheduler.scheduleAtFixedRate(new PeriodicTask(store, popAccount, request), 0, pollingInterval, TimeUnit.MINUTES);
String portalName = "unknown"; String portalName = "unknown";
try { try {
popAccount.getPortalName() ; portalName = popAccount.getPortalName() ;
} }
catch (NullPointerException e){ catch (NullPointerException e){
_log.warn("Could not read popAccount data portal name", e); _log.warn("Could not read popAccount data portal name", e);

View File

@ -2,26 +2,18 @@ package org.gcube.portal.socialmail;
import static org.gcube.common.authorization.client.Constants.authorizationService; 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.security.GeneralSecurityException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.UUID; 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 javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringEscapeUtils; 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.mailing.SocialMailingUtil;
import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingSite; import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingSite;
import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingUser; 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.SecurityTokenProvider;
import org.gcube.common.authorization.library.provider.UserInfo; import org.gcube.common.authorization.library.provider.UserInfo;
import org.gcube.common.portal.PortalContext; import org.gcube.common.portal.PortalContext;
import org.gcube.common.scope.api.ScopeProvider; 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.server.DatabookStore;
import org.gcube.portal.databook.shared.Comment; import org.gcube.portal.databook.shared.Comment;
import org.gcube.portal.databook.shared.Feed; 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.CommentNotificationsThread;
import org.gcube.portal.notifications.thread.LikeNotificationsThread; import org.gcube.portal.notifications.thread.LikeNotificationsThread;
import org.gcube.portal.notifications.thread.MessageNotificationsThread; 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.UserManager;
import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager; import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager;
import org.gcube.vomanagement.usermanagement.model.GCubeUser; 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.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.sun.mail.util.MailSSLSocketFactory; 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 * @author Massimiliano Assante, CNR-ISTI
@ -70,6 +80,7 @@ import com.sun.mail.util.MailSSLSocketFactory;
public class PeriodicTask implements Runnable { public class PeriodicTask implements Runnable {
private static final Log _log = LogFactoryUtil.getLog(PeriodicTask.class); 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 APP_ID_NEWSFEED = "org.gcube.portlets.user.newsfeed.server.NewsServiceImpl";
private static final String SHUB_MESSAGES_ENDPOINT = "workspace/messages/";
private DatabookStore socialStore; private DatabookStore socialStore;
private EmailPopAccount popAccount; private EmailPopAccount popAccount;
@ -136,6 +147,20 @@ public class PeriodicTask implements Runnable {
} }
return toReturn; return toReturn;
} }
private static String generateAuthorizationToken(String username, String scope) {
List<String> 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 final static String DEFAULT_ROLE = "OrganizationMember";
private static void setAuthorizationToken(ASLSession session) throws Exception { private static void setAuthorizationToken(ASLSession session) throws Exception {
@ -250,6 +275,16 @@ public class PeriodicTask implements Runnable {
* @throws Exception * @throws Exception
*/ */
private void handleMessageReply(String portalName, String messageId, Message message, ASLSession fakeSession) { 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 subject = "";
String messageText = ""; String messageText = "";
try { try {
@ -261,34 +296,23 @@ public class PeriodicTask implements Runnable {
_log.debug("Found message reply, subject: " + subject + " body: " + messageText); _log.debug("Found message reply, subject: " + subject + " body: " + messageText);
String newMessageId = null; String newMessageId = null;
List<String> recipientIds = new ArrayList<>(); ArrayList<String> recipientIds = new ArrayList<String>();
try { try {
String username = fakeSession.getUsername(); String username = fakeSession.getUsername();
String scope = fakeSession.getScope(); String context = fakeSession.getScope();
ScopeProvider.instance.set(scope); ScopeProvider.instance.set(context);
_log.debug("calling service token on scope " + scope); _log.debug("calling service token on context " + context);
List<String> userRoles = new ArrayList<>(); List<String> userRoles = new ArrayList<>();
userRoles.add(DEFAULT_ROLE); userRoles.add(DEFAULT_ROLE);
fakeSession.setSecurityToken(null); 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); SecurityTokenProvider.instance.set(token);
MessageManagerClient mmClient = AbstractPlugin.messages().build(); MessageInbox theMessage = null;
org.gcube.common.storagehub.model.messages.Message theMessage = null; _log.info("Looking for Message with id "+ messageId);
try { String messagesEndpoint = getStorageHubURLFromContext(context)+SHUB_MESSAGES_ENDPOINT;
theMessage = mmClient.get(messageId); theMessage = getMessageWSById(messagesEndpoint, messageId, token);
} _log.info("Got Message = " + theMessage.toString());
catch (IdNotFoundException e) {
_log.warn("Message with id "+ messageId + " could not be found, trying by name ...");
List<org.gcube.common.storagehub.model.messages.Message> 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;
}
}
}
if (theMessage != null) { if (theMessage != null) {
String[] addresses = theMessage.getAddresses(); String[] addresses = theMessage.getAddresses();
for (int i = 0; i < addresses.length; i++) { for (int i = 0; i < addresses.length; i++) {
@ -302,17 +326,20 @@ public class PeriodicTask implements Runnable {
recipientIds.remove(fakeSession.getUsername()); recipientIds.remove(fakeSession.getUsername());
_log.debug("Message Recipients:"); _log.debug("Message Recipients:");
ArrayList<Recipient> recipients = new ArrayList<Recipient>();
for (String rec : recipientIds) { for (String rec : recipientIds) {
recipients.add(new Recipient(rec));
_log.debug(rec); _log.debug(rec);
} }
_log.debug("Constructing reply message"); _log.debug("Constructing reply message");
messageText += getReplyHeaderMessage(sender, originalSentTime, originalText); messageText += getReplyHeaderMessage(sender, originalSentTime, originalText);
_log.debug("Trying to send message with subject: " + subject + " to: " + recipientIds.toString()); _log.debug("Trying to send message with subject: " + subject + " to: " + recipientIds.toString());
newMessageId = mmClient.sendMessage(recipientIds, subject, messageText, new ArrayList<String>()); MessageInputBean message2Send = new MessageInputBean(messageText, subject, recipients);
} else { MessageClient messagesClient = new MessageClient();
_log.error("Message with id "+ messageId + " could not be found even iterating by name, exiting."); newMessageId = messagesClient.writeMessage(message2Send);
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); 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) { private String getReplyHeaderMessage(String senderId, Date date, String message) {
List<String> toPass = new ArrayList<String>(); List<String> toPass = new ArrayList<String>();
toPass.add(senderId); toPass.add(senderId);
@ -376,6 +445,15 @@ public class PeriodicTask implements Runnable {
* @throws Exception * @throws Exception
*/ */
private void handlePostReply(String portalName, String postId, Message message, ASLSession fakeSession) 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); String commentText = extractText(portalName, postId, message);
_log.info("Extracted id: " + postId + " text=" + commentText); _log.info("Extracted id: " + postId + " text=" + commentText);
String escapedCommentText = org.gcube.portal.socialmail.Utils.escapeHtmlAndTransformUrl(commentText); String escapedCommentText = org.gcube.portal.socialmail.Utils.escapeHtmlAndTransformUrl(commentText);
@ -386,6 +464,7 @@ public class PeriodicTask implements Runnable {
likePost(postId, fakeSession); likePost(postId, fakeSession);
} }
else { else {
Comment comment = new Comment(UUID.randomUUID().toString(), fakeSession.getUsername(), Comment comment = new Comment(UUID.randomUUID().toString(), fakeSession.getUsername(),
new Date(), postId, escapedCommentText, fakeSession.getUserFullName(), fakeSession.getUserAvatarId()); new Date(), postId, escapedCommentText, fakeSession.getUserFullName(), fakeSession.getUserAvatarId());
@ -411,12 +490,21 @@ public class PeriodicTask implements Runnable {
* @param fakeSession * @param fakeSession
*/ */
private void likePost(String postId, ASLSession 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) { if (postId == null || postId.compareTo("") == 0) {
_log.warn("Found email with no feedId from " + fakeSession.getUserEmailAddress() + ". Going to trash it"); _log.warn("Found email with no feedId from " + fakeSession.getUserEmailAddress() + ". Going to trash it");
return; return;
} }
Like like = new Like(UUID.randomUUID().toString(), fakeSession.getUsername(), Like like = new Like(UUID.randomUUID().toString(), fakeSession.getUsername(),
new Date(), postId, fakeSession.getUserFullName(), fakeSession.getUserAvatarId()); new Date(), postId, fakeSession.getUserFullName(), fakeSession.getUserAvatarId());
@ -436,7 +524,7 @@ public class PeriodicTask implements Runnable {
NotificationsManager nm = new ApplicationNotificationsManager( NotificationsManager nm = new ApplicationNotificationsManager(
site, site,
fakeSession.getScope(), post.getVreid(),
new SocialNetworkingUser(fakeSession.getUsername(), fakeSession.getUserEmailAddress(), fakeSession.getUserFullName(), fakeSession.getUserAvatarId()), new SocialNetworkingUser(fakeSession.getUsername(), fakeSession.getUserEmailAddress(), fakeSession.getUserFullName(), fakeSession.getUserAvatarId()),
APP_ID_NEWSFEED APP_ID_NEWSFEED
); );