diff --git a/CHANGELOG.md b/CHANGELOG.md
index 634e76d..ef390ab 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,14 @@
# Changelog
+## [v2.9.0-SNAPSHOT] - 2023-02-13
+
+ - Feature #24456 social-networking rest api endpoints (comments, Likes, GetPost)
+
## [v2.8.0-SNAPSHOT] - 2022-10-20
- Feature #23891 Refactored following updates social lib
- Feature #23847 Social service: temporarily block of notifications for given username(s)
-- Feature #23439: Please allow an IAM client to send notifications OPEN
+- Feature #23439 Please allow an IAM client to send notifications OPEN
- Feature #23991 Support attachments through notification / message API
- Feature #23995 added support for set Message read / unread
- Feature #24022 added get posts By PostId with range filter parameters and get Comments By PostId
diff --git a/pom.xml b/pom.xml
index bd6fe3f..790753a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,7 @@
org.gcube.portal
social-networking-library-ws
war
- 2.8.0-SNAPSHOT
+ 2.9.0-SNAPSHOT
social-networking-library-ws
Rest interface for the social networking library.
diff --git a/src/main/java/org/gcube/portal/social/networking/ws/methods/v1/Messages.java b/src/main/java/org/gcube/portal/social/networking/ws/methods/v1/Messages.java
deleted file mode 100644
index f63e2a0..0000000
--- a/src/main/java/org/gcube/portal/social/networking/ws/methods/v1/Messages.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.gcube.portal.social.networking.ws.methods.v1;
-
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-
-import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder;
-import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
-import org.gcube.vomanagement.usermanagement.UserManager;
-import org.slf4j.LoggerFactory;
-
-/**
- * Messages services REST interface
- * @author Costantino Perciante at ISTI-CNR
- * (costantino.perciante@isti.cnr.it)
- */
-@Path("/messages")
-@Deprecated
-public class Messages {
- // Logger
- private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Messages.class);
-
- public Messages() {
- }
-
- @POST
- @Path("writeMessageToUsers/")
- @Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
- /**
- * Try to send a message to recipientsIds. The sender is the owner of the gcube-token if not otherwise stated.
- * @param body
- * @param subject
- * @return ok on success, error otherwise
- */
- @Deprecated
- public Response writeMessageToUsers(
- @FormParam("sender") String sender, // the optional sender, if missing the sender will be the token's owner.
- @FormParam("body") String body,
- @FormParam("subject") String subject,
- @FormParam("recipients") String recipientsIds) {
-
- if(body == null || body.isEmpty() || subject == null || subject.isEmpty() || recipientsIds == null || recipientsIds.isEmpty()){
- logger.error("Missing/wrong request parameters");
- return Response.status(Status.BAD_REQUEST).entity(ErrorMessages.MISSING_PARAMETERS).build();
- }
-
- return Response.status(Status.METHOD_NOT_ALLOWED).entity(ErrorMessages.DEPRECATED_METHOD).build();
- }
-}
diff --git a/src/main/java/org/gcube/portal/social/networking/ws/methods/v1/Users.java b/src/main/java/org/gcube/portal/social/networking/ws/methods/v1/Users.java
deleted file mode 100644
index 074d313..0000000
--- a/src/main/java/org/gcube/portal/social/networking/ws/methods/v1/Users.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.gcube.portal.social.networking.ws.methods.v1;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-
-import org.gcube.common.authorization.library.provider.AuthorizationProvider;
-import org.gcube.common.authorization.library.utils.Caller;
-import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder;
-import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
-import org.gcube.portal.social.networking.ws.utils.TokensUtils;
-import org.gcube.vomanagement.usermanagement.model.GCubeUser;
-import org.slf4j.LoggerFactory;
-
-/**
- * REST interface for the social networking library (users).
- */
-@Path("/users")
-@Deprecated
-public class Users {
- @GET
- @Path("getUserFullname")
- @Produces(MediaType.TEXT_PLAIN)
- @Deprecated
- public Response getUserUsername(){
- return Response.status(Status.METHOD_NOT_ALLOWED).entity(ErrorMessages.DEPRECATED_METHOD).build();
- }
-
- @GET
- @Path("getUserEmail")
- @Produces(MediaType.TEXT_PLAIN)
- @Deprecated
- public Response getUserEmail(){
- return Response.status(Status.METHOD_NOT_ALLOWED).entity(ErrorMessages.DEPRECATED_METHOD).build();
- }
-}
diff --git a/src/main/java/org/gcube/portal/social/networking/ws/methods/v2/Comments.java b/src/main/java/org/gcube/portal/social/networking/ws/methods/v2/Comments.java
index eec4b94..733af0b 100644
--- a/src/main/java/org/gcube/portal/social/networking/ws/methods/v2/Comments.java
+++ b/src/main/java/org/gcube/portal/social/networking/ws/methods/v2/Comments.java
@@ -134,7 +134,7 @@ public class Comments {
}
/*
- * Retrieve comments of the gcube-token's owner in the context bound to the token itself and filter them by date
+ * Retrieve comments of the token owner in the context bound to the token itself and filter them by date
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@@ -171,7 +171,7 @@ public class Comments {
/**
* Create a new comment to a post having as owner the auth token's owner
- * @param post The post to be written
+ * @param comment The CommentInputBean object
* @return
* @throws ValidationException
*/
diff --git a/src/main/java/org/gcube/portal/social/networking/ws/methods/v2/Likes.java b/src/main/java/org/gcube/portal/social/networking/ws/methods/v2/Likes.java
index b49eb0f..3f1d849 100644
--- a/src/main/java/org/gcube/portal/social/networking/ws/methods/v2/Likes.java
+++ b/src/main/java/org/gcube/portal/social/networking/ws/methods/v2/Likes.java
@@ -1,12 +1,16 @@
package org.gcube.portal.social.networking.ws.methods.v2;
+import java.util.Date;
import java.util.List;
+import javax.validation.Valid;
import javax.validation.ValidationException;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
+import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
+import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
@@ -17,11 +21,15 @@ import javax.ws.rs.core.Response.Status;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
+import org.gcube.portal.databook.shared.Comment;
import org.gcube.portal.databook.shared.Like;
+import org.gcube.portal.databook.shared.ex.FeedIDNotFoundException;
+import org.gcube.portal.social.networking.ws.inputs.CommentInputBean;
import org.gcube.portal.social.networking.ws.outputs.ResponseBean;
import org.gcube.portal.social.networking.ws.utils.CassandraConnection;
import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
import org.gcube.portal.social.networking.ws.utils.Filters;
+import org.gcube.portal.social.networking.ws.utils.SocialUtils;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
@@ -34,14 +42,14 @@ import com.webcohesion.enunciate.metadata.rs.StatusCodes;
*/
@Path("2/likes")
@RequestHeaders ({
- @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
- @RequestHeader( name = "Content-Type", description = "application/json")
- })
+ @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
+ @RequestHeader( name = "Content-Type", description = "application/json")
+})
public class Likes {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Likes.class);
-
+
/*
* Retrieve the list of likes belonging to the post id (key) of the token in the related context
* @param key the key as in the POST JSON representation
@@ -68,7 +76,7 @@ public class Likes {
List likes = null;
try{
- logger.info("Retrieving comments for user id " + username);
+ logger.info("Retrieving likes for user id " + username);
likes = CassandraConnection.getInstance().getDatabookStore().getAllLikesByPost(key);
responseBean.setResult(likes);
responseBean.setSuccess(true);
@@ -81,4 +89,83 @@ public class Likes {
return Response.status(status).entity(responseBean).build();
}
+
+ /**
+ * Create a new like to a post in the context of the token
+ * @param postid The post id to be liked
+ * @return true if everything is OK
+ * @throws ValidationException
+ */
+ @POST
+ @Path("like-post")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ @StatusCodes ({
+ @ResponseCode ( code = 201, condition = "Successful created, the like operation result is reported in the 'result' field of the returned object"),
+ @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
+ })
+ public Response like(
+ @NotNull(message="Post to like is missing")
+ @Valid
+ String postId) throws ValidationException {
+ Caller caller = AuthorizationProvider.instance.get();
+ String username = caller.getClient().getId();
+ logger.debug("Request of like coming from user " + username);
+ String context = ScopeProvider.instance.get();
+ ResponseBean responseBean = new ResponseBean();
+ Status status = Status.OK;
+ boolean likeResultOperation = SocialUtils.like(username, postId, context);
+ if (likeResultOperation)
+ logger.info("Added like OK to postId " + postId);
+ else {
+ logger.error("Unable to like this post"+ postId);
+ responseBean.setMessage("Unable to like, something went wrong please see server log");
+ responseBean.setSuccess(false);
+ status = Status.INTERNAL_SERVER_ERROR;
+ return Response.status(status).entity(responseBean).build();
+ }
+
+ responseBean.setResult(true);
+ responseBean.setSuccess(true);
+ return Response.status(status).entity(responseBean).build();
+ }
+
+ /**
+ * Unlike to a post in the context of the token
+ * @param postid The post id to be liked
+ * @return true if everything is OK
+ * @throws ValidationException
+ */
+ @POST
+ @Path("unlike-post")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ @StatusCodes ({
+ @ResponseCode ( code = 201, condition = "The unlike operation result is reported in the 'result' field of the returned object"),
+ @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
+ })
+ public Response unlike(
+ @NotNull(message="Post to unlike is missing")
+ @Valid
+ String postId) throws ValidationException {
+ Caller caller = AuthorizationProvider.instance.get();
+ String username = caller.getClient().getId();
+ logger.debug("Request of unlike coming from user " + username);
+ ResponseBean responseBean = new ResponseBean();
+ Status status = Status.OK;
+ boolean likeResultOperation = SocialUtils.unlike(username, postId);
+ if (likeResultOperation)
+ logger.info("Unlike OK to postId " + postId);
+ else {
+ logger.error("Unable to unlike this post"+ postId);
+ responseBean.setMessage("Unable to unlike, something went wrong please see server log");
+ responseBean.setSuccess(false);
+ status = Status.INTERNAL_SERVER_ERROR;
+ return Response.status(status).entity(responseBean).build();
+ }
+
+ responseBean.setResult(true);
+ responseBean.setSuccess(true);
+ return Response.status(status).entity(responseBean).build();
+ }
}
diff --git a/src/main/java/org/gcube/portal/social/networking/ws/utils/SocialUtils.java b/src/main/java/org/gcube/portal/social/networking/ws/utils/SocialUtils.java
index 39ffb2d..2aa483d 100644
--- a/src/main/java/org/gcube/portal/social/networking/ws/utils/SocialUtils.java
+++ b/src/main/java/org/gcube/portal/social/networking/ws/utils/SocialUtils.java
@@ -11,11 +11,13 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
-import java.util.Map.Entry;
+
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
+
import org.gcube.applicationsupportlayer.social.ApplicationNotificationsManager;
import org.gcube.applicationsupportlayer.social.NotificationsManager;
import org.gcube.applicationsupportlayer.social.ex.ApplicationProfileNotFoundException;
@@ -520,7 +522,7 @@ public class SocialUtils {
* @throws FeedIDNotFoundException
*/
public static Comment commentPost(String userid, Date time, String postId, String commentText, String postOwnerId, String context) throws FeedIDNotFoundException {
-
+
SocialMessageParser messageParser = new SocialMessageParser(commentText);
String escapedCommentText = messageParser.getParsedMessage();
//check if any mention exists
@@ -529,7 +531,7 @@ public class SocialUtils {
SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(ScopeProvider.instance.get());
escapedCommentText = Utils.convertMentionUsernamesAnchorHTML(escapedCommentText, mentionedUsersToConvertInHTML, site.getSiteURL(), site.getSiteLandingPagePath());
-
+
// retrieve user information
GCubeUser user;
UserManager uManager = UserManagerWSBuilder.getInstance().getUserManager();
@@ -543,19 +545,19 @@ public class SocialUtils {
String email = user.getEmail();
String fullName = user.getFirstName() + " " + user.getLastName();
String thumbnailURL = user.getUserAvatarURL();
-
+
Comment theComment = new Comment(commentKey, userid, time, postId, escapedCommentText, fullName, thumbnailURL);
logger.info("Attempting to save Comment with text: " + commentText + " postid="+postId);
-
+
boolean result = CassandraConnection.getInstance().getDatabookStore().addComment(theComment);
logger.info("Added comment? " + theComment.toString() + " Result is " +result);
-
+
if (!result)
return null;
-
+
//if the comment was correctly delivered notify users involved
SocialNetworkingUser socialUser = new SocialNetworkingUser(userid, email, fullName, thumbnailURL);
-
+
NotificationsManager nm = new ApplicationNotificationsManager(uManager, site, context, socialUser, NEWS_FEED_PORTLET_CLASSNAME);
//if the user who commented this post is not the user who posted it notify the poster user (Post owner)
@@ -568,7 +570,7 @@ public class SocialUtils {
ArrayList likes = getAllLikesByPost(postId);
Thread likesThread = new Thread(new LikeNotificationsThread(escapedCommentText, nm, likes, postOwnerId, theComment.getKey()));
likesThread.start();
-
+
//notify the other users who commented this post (excluding the ones above)
Thread commentsNotificationthread = new Thread(new CommentNotificationsThread(
CassandraConnection.getInstance().getDatabookStore(),
@@ -626,7 +628,7 @@ public class SocialUtils {
}
return theComment;
}
-
+
private static ArrayList getAllLikesByPost(String postid) {
ArrayList toReturn = (ArrayList) CassandraConnection.getInstance().getDatabookStore().getAllLikesByPost(postid);
logger.debug("Asking likes for " + postid);
@@ -646,4 +648,76 @@ public class SocialUtils {
}
return toReturn;
}
+
+ public static boolean like(String username, String postid, String context) {
+ boolean likeCommitResult = false;
+ // retrieve user information
+ GCubeUser user;
+ UserManager uManager = UserManagerWSBuilder.getInstance().getUserManager();
+ try {
+ user = uManager.getUserByUsername(username);
+ } catch(Exception e){
+ logger.error("Unable to get user informations, like write fails.", e);
+ return false;
+ }
+ String email = user.getEmail();
+ String fullName = user.getFirstName() + " " + user.getLastName();
+ String thumbnailURL = user.getUserAvatarURL();
+ SocialNetworkingUser socialUser = new SocialNetworkingUser(user.getUsername(), email, fullName, thumbnailURL);
+
+ Like toLike = new Like(UUID.randomUUID().toString(), user.getUsername(),
+ new Date(), postid, user.getFullname(), user.getUserAvatarURL());
+ Post thePost = null;
+ try {
+ thePost = CassandraConnection.getInstance().getDatabookStore().readPost(postid);
+ likeCommitResult = CassandraConnection.getInstance().getDatabookStore().like(toLike);
+ } catch (Exception e) {
+ logger.error("Post not Found for this like ot could not like the post " + e.getMessage());
+ return false;
+ }
+ //if the like was correctly delivered notify the user who made the post
+
+ boolean resultNotifyLike =false;
+ if (likeCommitResult) {
+ SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(ScopeProvider.instance.get());
+ NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, context, socialUser, NEWS_FEED_PORTLET_CLASSNAME);
+
+ String postText = thePost.getDescription();
+ String postOwnerId = thePost.getEntityId();
+ SocialMessageParser messageParser = new SocialMessageParser(postText);
+ String escapedPostText = messageParser.getParsedMessage();
+
+ //if the user who liked this post is not the user who posted it notify the poster user (Post owner)
+ logger.info("The post creator is " + postOwnerId);
+ if (! user.getUsername().equals(postOwnerId)) {
+ resultNotifyLike = nm.notifyLikedPost(postOwnerId, postid, escapedPostText);
+ logger.info("Like Notification to post creator added? " + resultNotifyLike);
+ }
+ }
+ return likeCommitResult && resultNotifyLike;
+ }
+
+ public static boolean unlike(String username, String postid) {
+ boolean unlikeCommitResult = false;
+ // retrieve user information
+ GCubeUser user;
+ UserManager uManager = UserManagerWSBuilder.getInstance().getUserManager();
+ try {
+ user = uManager.getUserByUsername(username);
+ } catch(Exception e){
+ logger.error("Unable to get user informations, unlike write fails.", e);
+ return false;
+ }
+ String fullName = user.getFirstName() + " " + user.getLastName();
+ String thumbnailURL = user.getUserAvatarURL();
+ try {
+
+ unlikeCommitResult = CassandraConnection.getInstance().getDatabookStore().unlike(username, fullName, thumbnailURL);
+ } catch (Exception e) {
+ logger.error("Post not Found for this like ot could not unlike the post " + e.getMessage());
+ return false;
+ }
+
+ return unlikeCommitResult;
+ }
}