package org.gcube.portal.social.networking.ws.methods.v2; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import javax.validation.ValidationException; import javax.validation.constraints.NotNull; import javax.ws.rs.Consumes; import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import org.gcube.applicationsupportlayer.social.ApplicationNotificationsManager; import org.gcube.applicationsupportlayer.social.NotificationsManager; import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingSite; import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingUser; import org.gcube.common.authorization.control.annotations.AuthorizationControl; import org.gcube.common.authorization.library.provider.AuthorizationProvider; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.authorization.library.utils.Caller; 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.messages.Message; import org.gcube.portal.notifications.bean.GenericItemBean; import org.gcube.portal.notifications.thread.MessageNotificationsThread; import org.gcube.portal.social.networking.caches.SocialNetworkingSiteFinder; import org.gcube.portal.social.networking.liferay.ws.LiferayJSONWsCredentials; import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder; import org.gcube.portal.social.networking.ws.ex.AuthException; import org.gcube.portal.social.networking.ws.inputs.UserSetNotificationBean; import org.gcube.portal.social.networking.ws.outputs.ResponseBean; import org.gcube.portal.social.networking.ws.utils.ErrorMessages; import org.gcube.portal.social.networking.ws.utils.TokensUtils; 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.exception.UserManagementSystemException; import org.gcube.vomanagement.usermanagement.exception.UserRetrievalFault; import org.gcube.vomanagement.usermanagement.model.GCubeUser; import org.slf4j.LoggerFactory; import com.webcohesion.enunciate.metadata.rs.RequestHeader; import com.webcohesion.enunciate.metadata.rs.RequestHeaders; import com.webcohesion.enunciate.metadata.rs.ResponseCode; import com.webcohesion.enunciate.metadata.rs.StatusCodes; /** * Messages services REST interface * @author Costantino Perciante at ISTI-CNR * (costantino.perciante@isti.cnr.it) */ @Path("2/messages") @RequestHeaders ({ @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), @RequestHeader( name = "Content-Type", description = "application/json") }) public class Messages { // Logger private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Messages.class); /** * Write a message to another user. The sender is the token's owner by default * @responseExample application/json {"success": true, "message": null, "result": "556142e3-d6f5-4550-b2fa-abe5626625d3"} * @param input The message to write" * @param httpServletRequest * @return see response example * @throws ValidationException * @throws UserManagementSystemException * @throws UserRetrievalFault */ @POST @Path("write-message/") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @StatusCodes ({ @ResponseCode ( code = 200, condition = "Successful write a message. Its id is reported in the 'result' field of the returned object"), @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) }) public Response writeMessage( @NotNull(message="Message to send is missing") @Valid MessageInputBean input, @Context HttpServletRequest httpServletRequest) throws ValidationException, UserManagementSystemException, UserRetrievalFault{ logger.debug("Incoming message bean is " + input); Caller caller = AuthorizationProvider.instance.get(); UserManager um = UserManagerWSBuilder.getInstance().getUserManager(); GCubeUser senderUser = null; SocialNetworkingUser user = null; // check if the token belongs to an application token. In this case use J.A.R.V.I.S (the username used to communicate with Liferay) String username = null; String fullName = ""; logger.debug("Catalogue Notification called by " + caller.getClient().getId() + " isUser?"+TokensUtils.isUserToken(caller)); if(!TokensUtils.isUserToken(caller)){ GCubeUser jarvis = UserManagerWSBuilder.getInstance().getUserManager().getUserByEmail(LiferayJSONWsCredentials.getSingleton().getUser()); SecurityTokenProvider.instance.set(LiferayJSONWsCredentials.getSingleton().getNotifierUserToken()); username = jarvis.getUsername(); fullName = caller.getClient().getId().replace("service-account-", ""); // the actual name of the IAM Client senderUser = um.getUserByUsername(username); user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), fullName, senderUser.getUserAvatarURL()); }else{ username = caller.getClient().getId(); senderUser = um.getUserByUsername(username); fullName = senderUser.getFullname(); user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), fullName, senderUser.getUserAvatarURL()); } String scope = ScopeProvider.instance.get(); ResponseBean responseBean = new ResponseBean(); Status status = Status.CREATED; String body = input.getBody(); String subject = input.getSubject(); List recipientsIds = input.getRecipients(); // "recipients":[{"recipient":"id recipient"}, ......] logger.info("Sender is going to be [" + fullName + "]"); // get the recipients ids (simple check, trim) List recipientsListFiltered = new ArrayList(); List recipientsBeans = new ArrayList(); for (Recipient recipientId : recipientsIds) { try{ String tempId = recipientId.getId().trim(); if(tempId.isEmpty()) continue; GCubeUser userRecipient = UserManagerWSBuilder.getInstance().getUserManager().getUserByUsername(tempId); if(userRecipient == null) userRecipient = UserManagerWSBuilder.getInstance().getUserManager().getUserByEmail(tempId); if(userRecipient != null){ GenericItemBean beanUser = new GenericItemBean(userRecipient.getUsername(), userRecipient.getUsername(), userRecipient.getFullname(), userRecipient.getUserAvatarURL()); recipientsBeans.add(beanUser); recipientsListFiltered.add(userRecipient.getUsername()); } }catch(Exception e){ logger.error("Unable to retrieve recipient information for recipient with id " + recipientId, e); } } if(recipientsListFiltered.isEmpty()){ logger.error("Missing/wrong request parameters"); status = Status.BAD_REQUEST; responseBean.setMessage(ErrorMessages.MISSING_PARAMETERS); return Response.status(status).entity(responseBean).build(); } try{ logger.debug("Trying to send message with body " + body + " subject " + subject + " to users " + recipientsIds + " from " + username); // send message MessageManagerClient client = AbstractPlugin.messages().build(); logger.debug("Sending message to " + recipientsListFiltered); String messageId = client.sendMessage(recipientsListFiltered, subject, body, input.getAttachmentIds()); // send notification logger.debug("Message sent to " + recipientsIds + ". Sending message notification to: " + recipientsIds); SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(scope); NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, ScopeProvider.instance.get(), user); new Thread(new MessageNotificationsThread(recipientsBeans, messageId, subject, body, nm)).start(); responseBean.setSuccess(true); responseBean.setResult(messageId); }catch(Exception e){ logger.error("Unable to send message.", e); status = Status.INTERNAL_SERVER_ERROR; responseBean.setMessage(e.toString()); } return Response.status(status).entity(responseBean).build(); } @GET @Path("get-sent-messages") @Produces(MediaType.APPLICATION_JSON) @StatusCodes ({ @ResponseCode ( code = 200, condition = "Successful read of the sent messages, reported in the 'result' field of the returned object"), @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) }) /** * * @return the list of sent messages of the user (the token's owner) */ public Response getSentMessages(){ Caller caller = AuthorizationProvider.instance.get(); String username = caller.getClient().getId(); ResponseBean responseBean = new ResponseBean(); Status status = Status.OK; logger.info("Request for retrieving sent messages by " + username); try{ MessageManagerClient client = AbstractPlugin.messages().build(); List sentMessages = client.getSentMessages(); Collections.reverse(sentMessages); responseBean.setSuccess(true); logger.debug("Result is " + sentMessages); responseBean.setResult(sentMessages); }catch(Exception e){ logger.error("Unable to retrieve sent messages", e); responseBean.setMessage(e.getMessage()); status = Status.INTERNAL_SERVER_ERROR; } return Response.status(status).entity(responseBean).build(); } @GET @Path("get-received-messages") @Produces(MediaType.APPLICATION_JSON) @StatusCodes ({ @ResponseCode ( code = 200, condition = "Successful read of the received messages, reported in the 'result' field of the returned object"), @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) }) /** * * @return the list of received messages of the user (the token's owner) */ public Response getReceivedMessages(){ Caller caller = AuthorizationProvider.instance.get(); String username = caller.getClient().getId(); ResponseBean responseBean = new ResponseBean(); Status status = Status.OK; logger.info("Request for retrieving received messages by " + username); try{ MessageManagerClient client = AbstractPlugin.messages().build(); List getMessages =client.getReceivedMessages(); Collections.reverse(getMessages); responseBean.setSuccess(true); responseBean.setResult(getMessages); }catch(Exception e){ logger.error("Unable to retrieve sent messages", e); responseBean.setMessage(e.getMessage()); status = Status.INTERNAL_SERVER_ERROR; } return Response.status(status).entity(responseBean).build(); } /** * Set message read or unread * @param messageId the message identifier * @param read true to set read, false to set unread * @return the result of the operation * @throws ValidationException */ @POST @Path("set-message-read/") @Produces(MediaType.APPLICATION_JSON) @StatusCodes ({ @ResponseCode ( code = 200, condition = "Message set Read or Unread is correctly executed"), @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) }) public Response setMessageRead( @NotNull(message="input is missing") @FormParam("messageId") String messageId, @FormParam("read") Boolean read) throws ValidationException{ Caller caller = AuthorizationProvider.instance.get(); ResponseBean responseBean = new ResponseBean(); Status status = Status.OK; String opExecutor = ""; try{ opExecutor = caller.getClient().getId(); MessageManagerClient client = AbstractPlugin.messages().build(); client.setRead(messageId, read); String toReturn = "set Message id:" + messageId + (read ? " read" : " unread"); logger.info("set Message id:" + messageId + " read?" + read + " for " + opExecutor); responseBean.setSuccess(true); responseBean.setResult(toReturn); } catch(Exception e){ logger.error("Unable to set message read / unread property for user " + opExecutor, e); responseBean.setSuccess(false); responseBean.setMessage(e.getMessage()); status = Status.INTERNAL_SERVER_ERROR; } return Response.status(status).entity(responseBean).build(); } }