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">
<wb-module deploy-name="social-mail-servlet">
<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="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<property name="context-root" value="social-mail-servlet"/>
<property name="java-output-path" value="/social-mail-servlet/target/classes"/>
</wb-module>
</project-modules>

View File

@ -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

23
pom.xml
View File

@ -12,7 +12,7 @@
<groupId>org.gcube.portal</groupId>
<artifactId>social-mail-servlet</artifactId>
<packaging>war</packaging>
<version>2.5.0</version>
<version>3.0.0-SNAPSHOT</version>
<scm>
<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>
@ -37,7 +37,7 @@
<dependency>
<groupId>org.gcube.distribution</groupId>
<artifactId>maven-portal-bom</artifactId>
<version>3.6.3</version>
<version>3.7.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -71,15 +71,22 @@
<artifactId>aslsocial</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>storagehub-client-library</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.portal</groupId>
<artifactId>social-networking-library</artifactId>
<scope>provided</scope>
</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>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
@ -109,8 +116,8 @@
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<scope>provided</scope>
<artifactId>jakarta.mail</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<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.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);

View File

@ -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<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 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<String> recipientIds = new ArrayList<>();
ArrayList<String> recipientIds = new ArrayList<String>();
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<String> 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<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;
}
}
}
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<Recipient> recipients = new ArrayList<Recipient>();
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<String>());
} 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<String> toPass = new ArrayList<String>();
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
);