package org.gcube.portal.social.networking.ws.methods.v2; import java.util.Arrays; 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.DefaultValue; 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; 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.library.provider.AuthorizationProvider; import org.gcube.common.authorization.library.utils.Caller; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.portal.databook.shared.Notification; import org.gcube.portal.databook.shared.RunningJob; import org.gcube.portal.notifications.bean.GenericItemBean; import org.gcube.portal.notifications.thread.JobStatusNotificationThread; 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.mappers.JobMapper; import org.gcube.portal.social.networking.ws.mappers.WorkspaceItemMapper; 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.social_networking.socialnetworking.model.beans.JobNotificationBean; import org.gcube.social_networking.socialnetworking.model.beans.WorkspaceNotification; import org.gcube.social_networking.socialnetworking.model.beans.WorkspaceNotificationAddedItem; import org.gcube.social_networking.socialnetworking.model.beans.WorkspaceNotificationSharedFolder; import org.gcube.social_networking.socialnetworking.model.beans.WorkspaceNotificationUnsharedFolder; 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; /** * REST interface for the social networking library (notifications). */ @Path("2/notifications") @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 Notifications { // Logger private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Notifications.class); @GET @Path("get-range-notifications/") @Produces(MediaType.APPLICATION_JSON) /** * Retrieve notifications of the gcube-token's owner * @param from must be greater or equal to 1, range[0, infinity] * @param quantity quantity must be greater or equal to 0 * @return notifications up to quantity * @throws ValidationException */ @StatusCodes ({ @ResponseCode ( code = 200, condition = "Notifications retrieved and reported in the 'result' field of the returned object"), @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) }) public Response getRangeNotifications( @DefaultValue("1") @QueryParam("from") @Min(value=1, message="from must be greater or equal to 1") int from, @DefaultValue("10") @QueryParam("quantity") @Min(value=0, message="quantity must be greater or equal to 0") int quantity ) throws ValidationException{ Caller caller = AuthorizationProvider.instance.get(); String username = caller.getClient().getId(); logger.debug("Retrieving " + quantity + " notifications of user = " + username + " from " + from); ResponseBean responseBean = new ResponseBean(); Status status = Status.OK; List notifications = null; try{ notifications = CassandraConnection.getInstance().getDatabookStore().getRangeNotificationsByUser(username, from, quantity); responseBean.setResult(notifications); responseBean.setSuccess(true); logger.debug("List of notifications retrieved"); }catch(Exception e){ logger.error("Unable to retrieve such notifications.", e); responseBean.setMessage(e.getMessage()); responseBean.setSuccess(false); status = Status.INTERNAL_SERVER_ERROR; } return Response.status(status).entity(responseBean).build(); } /** * Send a JOB notification to a given recipient * @param job The job bean * @return * @throws ValidationException */ @POST @Path("notify-job-status/") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @StatusCodes ({ @ResponseCode ( code = 200, condition = "Notification is sent correctly"), @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) }) public Response notifyJobStatus( @NotNull(message="input is missing") @Valid JobNotificationBean job) throws ValidationException{ Caller caller = AuthorizationProvider.instance.get(); String context = ScopeProvider.instance.get(); ResponseBean responseBean = new ResponseBean(); Status status = Status.OK; String appQualifier = caller.getClient().getId(); logger.info("Received request from app " + appQualifier + " to notify job status described by bean " + job); try{ String recipient = job.getRecipient(); GCubeUser userRecipient = UserManagerWSBuilder.getInstance().getUserManager().getUserByUsername(recipient); GenericItemBean recipientBean = new GenericItemBean(userRecipient.getUsername(), userRecipient.getUsername(), userRecipient.getFullname(), userRecipient.getUserAvatarURL()); // notifications are sent by using the user allowed to use liferay's json apis SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(context); GCubeUser senderUser = UserManagerWSBuilder.getInstance().getUserManager().getUserByEmail(LiferayJSONWsCredentials.getSingleton().getUser()); SocialNetworkingUser user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), senderUser.getFullname(), senderUser.getUserAvatarURL()); NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, context, user); RunningJob theJob = JobMapper.getJob(job); new Thread(new JobStatusNotificationThread(theJob, Arrays.asList(recipientBean), nm)).start(); responseBean.setSuccess(true); responseBean.setResult("Notification thread started"); }catch(Exception e){ logger.error("Unable to send job notification", e); responseBean.setSuccess(false); responseBean.setMessage(e.getMessage()); status = Status.INTERNAL_SERVER_ERROR; } return Response.status(status).entity(responseBean).build(); } /** * Send a Workspace notification to a given user * @param message * @return * @throws ValidationException */ @POST @Path("workspace/") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @StatusCodes ({ @ResponseCode ( code = 200, condition = "Workspace Notification is sent correctly"), @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) }) public Response workspace( @NotNull(message="input is missing") @Valid WorkspaceNotification message) throws ValidationException{ Caller caller = AuthorizationProvider.instance.get(); String context = ScopeProvider.instance.get(); String username = caller.getClient().getId(); if (!message.getType().getNotificationClass().isInstance(message)) { //invalid call return Response.status(Status.BAD_REQUEST).build(); } ResponseBean responseBean = new ResponseBean(); Status status = Status.OK; try{ SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(context); GCubeUser senderUser = UserManagerWSBuilder.getInstance().getUserManager().getUserByUsername(username); SocialNetworkingUser user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), senderUser.getFullname(), senderUser.getUserAvatarURL()); NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, context, user); switch (message.getType()) { case ITEM_NEW: { WorkspaceNotificationAddedItem itemBean = (WorkspaceNotificationAddedItem) message; String userIdToNotify = itemBean.getUserIdToNotify(); nm.notifyAddedItem(userIdToNotify, WorkspaceItemMapper.getFileItem(itemBean.getItem()), WorkspaceItemMapper.getSharedFolder(itemBean.getFolder())); break; } case FOLDER_SHARE: { WorkspaceNotificationSharedFolder itemBean = (WorkspaceNotificationSharedFolder) message; String userIdToNotify = itemBean.getUserIdToNotify(); nm.notifyFolderSharing(userIdToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder())); break; } case FOLDER_UNSHARE: { WorkspaceNotificationUnsharedFolder itemBean = (WorkspaceNotificationUnsharedFolder) message; String userIdToNotify = itemBean.getUserIdToNotify(); nm.notifyFolderUnsharing(userIdToNotify, itemBean.getUnsharedFolderId(), itemBean.getUnsharedFolderName()); break; } default: break; } } catch(Exception e){ logger.error("Unable to send job notification", e); responseBean.setSuccess(false); responseBean.setMessage(e.getMessage()); status = Status.INTERNAL_SERVER_ERROR; } return Response.status(status).entity(responseBean).build(); } }