Compare commits

..

No commits in common. "master" and "getPostByVREAndRange" have entirely different histories.

37 changed files with 741 additions and 2783 deletions

View File

@ -20,12 +20,12 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>

View File

@ -1,10 +1 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="social-networking-library-ws-3.0.0-SNAPSHOT">
<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-networking-library-ws"/>
<property name="java-output-path" value="/social-networking-library-ws/target/classes"/>
</wb-module>
</project-modules>
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId"/>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="wst.jsdt.web"/>
<installed facet="java" version="1.8"/>
<installed facet="jst.web" version="3.0"/>
<installed facet="jst.jaxrs" version="2.1"/>
<installed facet="wst.jsdt.web" version="1.0"/>
<installed facet="jst.jaxrs" version="1.1"/>
<installed facet="java" version="1.8"/>
</faceted-project>

View File

@ -1,33 +1,12 @@
# Changelog
## [v3.0.1] - 2023-04-22
- Feature 27286: removed noisy logs
- Bug 27218: advance social networking library version
## [v3.0.0-SNAPSHOT] - 2023-12-06
- Feature #26193, new impl for get users by role in a VRE
- Replace Astyanx Java client for Cassandra 2 with Datastax client for Cassandra 4
- Add REST resources for all the functions in social networking library
## [v2.9.1] - 2023-09-28
- Fix for Bug #25760 not closing connection to distributed cached
- Removed memcached dep
## [v2.9.0] - 2023-02-13
- Feature #24456 social-networking rest api endpoints (comments, Likes, GetPost)
## [v2.8.0] - 2022-10-20
## [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
## [v2.7.0] - 2022-09-12

View File

@ -22,12 +22,10 @@ See [Releases](https://code-repo.d4science.org/gCubeSystem/social-networking-lib
* **Massimiliano Assante** ([ORCID](https://orcid.org/0000-0002-3761-1492)) - [ISTI-CNR Infrascience Group](https://www.isti.cnr.it/People/M.Assante)
* **Costantino Perciante**
* **Ahmed Ibrahim** ([ORCID](https://orcid.org/0009-0001-3009-5755)) - [ISTI-CNR Infrascience Group](https://www.isti.cnr.it/en/about/people-detail/976/Ahmed_Salah_Tawfik_Ibrahim)
## Maintainers
* **Massimiliano Assante** ([ORCID](https://orcid.org/0000-0002-3761-1492)) - [ISTI-CNR Infrascience Group](https://www.isti.cnr.it/People/M.Assante)
* **Ahmed Ibrahim** ([ORCID](https://orcid.org/0009-0001-3009-5755)) - [ISTI-CNR Infrascience Group](https://www.isti.cnr.it/en/about/people-detail/976/Ahmed_Salah_Tawfik_Ibrahim)
## License
@ -40,4 +38,4 @@ open-source software toolkit used for building and operating Hybrid Data
Infrastructures enabling the dynamic deployment of Virtual Research Environments
by favouring the realisation of reuse oriented policies.
The projects leading to this software have received funding from a series of European Union programmes see [FUNDING.md](FUNDING.md)
The projects leading to this software have received funding from a series of European Union programmes see [FUNDING.md](FUNDING.md)

View File

@ -26,7 +26,7 @@ Base URL
In the production environment, its current value is https://api.d4science.org/rest
Authorization (how to contact the service)
Authorization
==================
D4Science adopts state-of-the-art industry standards for authentication and authorization.

216
pom.xml
View File

@ -6,31 +6,28 @@
<parent>
<groupId>org.gcube.tools</groupId>
<artifactId>maven-parent</artifactId>
<version>1.2.0</version>
<version>1.1.0</version>
</parent>
<groupId>org.gcube.portal</groupId>
<artifactId>social-networking-library-ws</artifactId>
<packaging>war</packaging>
<version>3.0.1</version>
<version>2.8.0-SNAPSHOT</version>
<name>social-networking-library-ws</name>
<description>Rest interface for the social networking library.</description>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<enunciate.version>2.14.0</enunciate.version>
<cassandra.driver.oss.version>4.13.0</cassandra.driver.oss.version>
<jackson.version>2.12.6</jackson.version>
<jackson.version>2.8.11</jackson.version>
<webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<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>
<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>
<url>https://code-repo.d4science.org/gCubeSystem/${project.artifactId}</url>
</scm>
@ -82,6 +79,11 @@
<artifactId>ehcache</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>net.spy</groupId>
<artifactId>spymemcached</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>authorization-control-library</artifactId>
@ -96,7 +98,7 @@
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>storagehub-client-library</artifactId>
<!-- <version>2.0.0-SNAPSHOT</version> -->
<!-- <version>2.0.0-SNAPSHOT</version> -->
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
@ -127,6 +129,58 @@
<artifactId>slf4j-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.netflix.astyanax</groupId>
<artifactId>astyanax</artifactId>
<version>2.0.2</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>jersey-client</artifactId>
<groupId>com.sun.jersey</groupId>
</exclusion>
<exclusion>
<artifactId>jersey-bundle</artifactId>
<groupId>com.sun.jersey</groupId>
</exclusion>
<exclusion>
<artifactId>jersey-apache-client4</artifactId>
<groupId>com.sun.jersey.contribs</groupId>
</exclusion>
<exclusion>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.mortbay.jetty</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.netflix.astyanax</groupId>
<artifactId>astyanax-thrift</artifactId>
<version>2.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.netflix.astyanax</groupId>
<artifactId>astyanax-cassandra</artifactId>
<version>2.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.netflix.astyanax</groupId>
<artifactId>astyanax-core</artifactId>
<version>2.0.2</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.gcube.socialnetworking</groupId>
<artifactId>social-util-library</artifactId>
@ -136,7 +190,7 @@
<dependency>
<groupId>org.gcube.portal</groupId>
<artifactId>social-networking-library</artifactId>
<version>[2.0.0, 3.0.0)</version>
<version>[1.18.0-SNAPSHOT, 2.0.0-SNAPSHOT)</version>
<scope>compile</scope>
</dependency>
<dependency>
@ -178,78 +232,26 @@
<version>[1.0.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-admin-client</artifactId>
<version>21.0.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-smile</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-cbor</artifactId>
<version>2.8.6</version>
</dependency>
<!-- needed by the search-->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>com.datastax.oss</groupId>
<artifactId>java-driver-query-builder</artifactId>
<version>${cassandra.driver.oss.version}</version>
</dependency>
<dependency>
<groupId>com.datastax.oss</groupId>
<artifactId>java-driver-mapper-runtime</artifactId>
<version>${cassandra.driver.oss.version}</version>
</dependency>
<dependency>
<groupId>com.google</groupId>
<artifactId>gwt-jsonmaker</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
<artifactId>jackson-dataformat-cbor</artifactId>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<version>2.8.6</version>
</dependency>
<!-- Please note that the elasticsearch client needs a compress-lzf
version
<!-- Please note that the elasticsearch client needs a compress-lzf version
>= 1.0.2 -->
<dependency>
<groupId>com.ning</groupId>
@ -259,8 +261,7 @@
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<!-- if your container implements Servlet API older than 3.0, use
"jersey-container-servlet-core" -->
<!-- if your container implements Servlet API older than 3.0, use "jersey-container-servlet-core" -->
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
<dependency>
@ -313,30 +314,47 @@
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>6.1.22</version>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
<version>4.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.14.0</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<aspectLibraries>
<aspectLibrary>
<groupId>org.gcube.common</groupId>
<artifactId>authorization-control-library</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>kr.motd.maven</groupId>
<artifactId>sphinx-maven-plugin</artifactId>
<version>2.10.0</version>
<configuration>
<outputDirectory>
${project.build.directory}/${project.artifactId}-${project.version}/docs</outputDirectory>
<outputDirectory>${project.build.directory}/${project.artifactId}-${project.version}/docs</outputDirectory>
<builder>html</builder>
<configDirectory>${basedir}/docs</configDirectory>
<sourceDirectory>${basedir}/docs</sourceDirectory>
@ -358,8 +376,7 @@
<configuration>
<sourcepath-includes>
<sourcepath-include>
<!-- Include the "com.external:external" artifact on
the sourcepath. -->
<!-- Include the "com.external:external" artifact on the sourcepath. -->
<groupId>org.gcube.social-networking</groupId>
<artifactId>social-service-model</artifactId>
</sourcepath-include>
@ -382,8 +399,7 @@
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
</plugin>
<!-- Copy Enunciate Documentation from your-application/docs to
your-application.war -->
<!-- Copy Enunciate Documentation from your-application/docs to your-application.war -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
@ -399,10 +415,8 @@
<outputDirectory>target</outputDirectory>
<resources>
<resource>
<targetPath>
${project.build.directory}/${project.artifactId}-${project.version}/api-docs</targetPath>
<directory>
${project.build.directory}/api-docs</directory>
<targetPath>${project.build.directory}/${project.artifactId}-${project.version}/api-docs</targetPath>
<directory>${project.build.directory}/api-docs</directory>
<filtering>true</filtering>
</resource>
</resources>
@ -410,6 +424,24 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<additionalparam>-Xdoclint:none</additionalparam>
<additionalJOption>-Xdoclint:none</additionalJOption>
</configuration>
<version>3.1.0</version>
<executions>
<execution>
<id>generate-doc</id>
<phase>install</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -16,7 +16,7 @@ public class GroupsCache {
*/
private GroupsCache(){
logger.debug("Building cache");
logger.info("Building cache");
CachesManager.getCache(CachesManager.GROUPS_CACHE);
}
@ -30,7 +30,7 @@ public class GroupsCache {
/**
* Retrieve an entry
* @param groupId
* @param id
* @return user associated to the user
*/
public GCubeGroup getGroup(long groupId){
@ -44,7 +44,7 @@ public class GroupsCache {
/**
* Save an entry into the cache
* @param id
* @param group
* @param user
*/
public void pushEntry(long id, GCubeGroup group){
Ehcache groupsCache = CachesManager.getCache(CachesManager.GROUPS_CACHE);

View File

@ -55,7 +55,7 @@ public class SocialNetworkingSiteFinder {
// read fallback properties
try{
logger.debug("Trying to read config.properties");
logger.info("Trying to read config.properties");
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("config.properties");
Properties properties = new Properties();
@ -90,11 +90,11 @@ public class SocialNetworkingSiteFinder {
if(scope == null || scope.isEmpty())
throw new IllegalArgumentException("Scope cannot be null/empty");
if(socialSitesCache != null && socialSitesCache.get(scope) != null)
if(socialSitesCache.get(scope) != null)
return (SocialNetworkingSite) socialSitesCache.get(scope).getObjectValue();
else{
SocialNetworkingSite site = discoverSite(scope);
if(socialSitesCache != null && site != null)
if(site != null)
socialSitesCache.put(new Element(scope, site));
return site;
}
@ -140,7 +140,7 @@ public class SocialNetworkingSiteFinder {
if(gatewayVirtualGroups != null && !gatewayVirtualGroups.isEmpty()){
for (VirtualGroup gatewayVirtualGroup : gatewayVirtualGroups) {
if(virtualGroupsOfGroup.contains(gatewayVirtualGroup)){
logger.debug("Matching gateway for scope " + scope + " is " + gateway);
logger.info("Matching gateway for scope " + scope + " is " + gateway);
matchingGateway = gateway;
break ext_loop;
}

View File

@ -33,7 +33,7 @@ public class UsersCache{
new Thread(){
public void run() {
try{
logger.debug("Fetching users and putting them into cache");
logger.info("Fetching users and putting them into cache");
Ehcache usersCache = CachesManager.getCache(CachesManager.USERS_CACHE);
GroupManager groupManager = GroupManagerWSBuilder.getInstance().getGroupManager();
UserManager userManager = UserManagerWSBuilder.getInstance().getUserManager();
@ -59,7 +59,7 @@ public class UsersCache{
/**
* Retrieve an entry
* @param userId
* @param id
* @return user associated to the user
*/
public GCubeUser getUser(long userId){

View File

@ -17,7 +17,7 @@ public class GroupManagerWSBuilder {
private GroupManagerWSBuilder(){
logger.debug("Building GroupManager please wait");
logger.info("Building GroupManager please wait");
try{
groupManagerWs = new LiferayWSGroupManager(
@ -31,7 +31,7 @@ public class GroupManagerWSBuilder {
return;
}
logger.debug("GroupManager instance built");
logger.info("GroupManager instance built");
}

View File

@ -1,143 +0,0 @@
package org.gcube.portal.social.networking.liferay.ws;
import static org.gcube.resources.discovery.icclient.ICFactory.clientFor;
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.gcube.common.encryption.encrypter.StringEncrypter;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint;
import org.gcube.common.resources.gcore.ServiceEndpoint.Property;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.resources.discovery.client.api.DiscoveryClient;
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
import org.gcube.smartgears.ContextProvider;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class KeycloakAPICredentials {
private static final Logger logger = LoggerFactory.getLogger(KeycloakAPICredentials.class);
// the singleton obj
private static KeycloakAPICredentials singleton = new KeycloakAPICredentials();
// properties that it contains
private String keycloakURL;
private String realm;
private String clientid;
private String password;
// Service endpoint properties
private final static String RUNTIME_RESOURCE_NAME = "IAM";
private final static String CATEGORY = "Service";
/**
* Private constructor
*/
private KeycloakAPICredentials() {
logger.debug("Building KeycloakAPICredentials object");
lookupPropertiesFromIs();
logger.debug("KeycloakAPICredentials object built");
}
/**
* Read the properties from the infrastructure
*/
private void lookupPropertiesFromIs() {
logger.debug("Starting creating KeycloakAPICredentials");
String oldContext = ScopeProvider.instance.get();
ApplicationContext ctx = ContextProvider.get(); // get this info from SmartGears
ScopeProvider.instance.set("/"+ctx.container().configuration().infrastructure());
logger.debug("Discovering liferay user's credentials in context " + ctx.container().configuration().infrastructure());
try{
List<ServiceEndpoint> resources = getConfigurationFromIS();
if (resources.size() == 0){
logger.error("There is no Runtime Resource having name " + RUNTIME_RESOURCE_NAME +" and Category " + CATEGORY + " in this scope.");
throw new Exception("There is no Runtime Resource having name " + RUNTIME_RESOURCE_NAME +" and Category " + CATEGORY + " in this scope.");
}
else {
for (ServiceEndpoint res : resources) {
Iterator<AccessPoint> accessPointIterator = res.profile().accessPoints().iterator();
while (accessPointIterator.hasNext()) {
ServiceEndpoint.AccessPoint accessPoint = (ServiceEndpoint.AccessPoint) accessPointIterator
.next();
if(accessPoint.name().equals("d4science")){
keycloakURL = accessPoint.address();
realm = accessPoint.name();
clientid = accessPoint.username();
password = StringEncrypter.getEncrypter().decrypt(accessPoint.password());
logger.info("Found accesspoint URL = " + keycloakURL);
}
}
}
}
}catch(Exception e){
logger.error("Unable to retrieve such service endpoint information!", e);
return;
}finally{
if(oldContext != null)
ScopeProvider.instance.set(oldContext);
}
logger.debug("Bean built " + toString());
}
/**
* Retrieve endpoints information from IS for DB
* @return list of endpoints for ckan database
* @throws Exception
*/
private List<ServiceEndpoint> getConfigurationFromIS() throws Exception{
SimpleQuery query = queryFor(ServiceEndpoint.class);
query.addCondition("$resource/Profile/Name/text() eq '"+ RUNTIME_RESOURCE_NAME +"'");
query.addCondition("$resource/Profile/Category/text() eq '"+ CATEGORY +"'");
DiscoveryClient<ServiceEndpoint> client = clientFor(ServiceEndpoint.class);
List<ServiceEndpoint> toReturn = client.submit(query);
return toReturn;
}
public static KeycloakAPICredentials getSingleton() {
if (singleton == null)
singleton = new KeycloakAPICredentials();
return singleton;
}
public String getServerURL() {
return keycloakURL;
}
public String getClientid() {
return clientid;
}
public String getPassword() {
return password;
}
public String getRealm() {
return realm;
}
@Override
public String toString() {
return "KeycloakAPICredentials [keycloakURL=" + keycloakURL + ", realm=" + realm + ", clientid=" + clientid
+ ", password=**************]";
}
}

View File

@ -7,7 +7,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.gcube.common.encryption.encrypter.StringEncrypter;
import org.gcube.common.encryption.StringEncrypter;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint;
import org.gcube.common.resources.gcore.ServiceEndpoint.Property;
@ -52,10 +52,10 @@ public class LiferayJSONWsCredentials {
* Private constructor
*/
private LiferayJSONWsCredentials() {
logger.debug("Building LiferayJSONWsCredentials object");
logger.info("Building LiferayJSONWsCredentials object");
loadNotifierToken();
lookupPropertiesFromIs();
logger.debug("LiferayJSONWsCredentials object built");
logger.info("LiferayJSONWsCredentials object built");
}
/**
@ -75,7 +75,7 @@ public class LiferayJSONWsCredentials {
*/
private void lookupPropertiesFromIs() {
logger.debug("Starting creating LiferayJSONWsCredentials");
logger.info("Starting creating LiferayJSONWsCredentials");
String oldContext = ScopeProvider.instance.get();
ApplicationContext ctx = ContextProvider.get(); // get this info from SmartGears
@ -118,7 +118,7 @@ public class LiferayJSONWsCredentials {
ScopeProvider.instance.set(oldContext);
}
logger.debug("Bean built " + toString());
logger.info("Bean built " + toString());
}
/**

View File

@ -17,7 +17,7 @@ public class RoleManagerWSBuilder {
private RoleManagerWSBuilder(){
logger.debug("Building UserManager please wait");
logger.info("Building UserManager please wait");
try{
roleManagerWs = new LiferayWSRoleManager(
@ -31,7 +31,7 @@ public class RoleManagerWSBuilder {
return;
}
logger.debug("UserManager instance built");
logger.info("UserManager instance built");
}

View File

@ -17,7 +17,7 @@ public class UserManagerWSBuilder {
private UserManagerWSBuilder(){
logger.debug("Building UserManager please wait");
logger.info("Building UserManager please wait");
try{
userManagerWs = new LiferayWSUserManager(
@ -31,7 +31,7 @@ public class UserManagerWSBuilder {
return;
}
logger.debug("UserManager instance built");
logger.info("UserManager instance built");
}

View File

@ -10,7 +10,7 @@ import org.slf4j.LoggerFactory;
/**
* Exception gets thrown when @Valid fail
* Exception thrown when @Valid fail
*/
@Provider
public class ApplicationException implements ExceptionMapper<Exception> {

View File

@ -1,72 +0,0 @@
package org.gcube.portal.social.networking.ws.inputs;
import java.io.Serializable;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.webcohesion.enunciate.metadata.DocumentationExample;
/**
* Generic input bean for methods that allow to comment posts
*/
@JsonIgnoreProperties(ignoreUnknown = true) // ignore in serialization/deserialization
public class CommentInputBean implements Serializable{
private static final long serialVersionUID = 5274608088828232980L;
@JsonProperty("text")
@NotNull(message="text cannot be null")
@Size(min=1, message="text cannot be empty")
@DocumentationExample("I would like to comment that ...")
/**
* text the text of the comment
*/
private String text;
@NotNull(message="postid cannot be null")
@JsonProperty("postid")
/**
* postid the postid of the post where you attach the comment
*/
private String postid;
public CommentInputBean() {
super();
}
/**
* @param text
* @param postid
*/
public CommentInputBean(String text, String postid) {
super();
this.text = text;
this.postid = postid;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getPostid() {
return postid;
}
public void setPostid(String postid) {
this.postid = postid;
}
@Override
public String toString() {
return "CommentInputBean [text=" + text + ", postid=" + postid + "]";
}
}

View File

@ -1,60 +0,0 @@
package org.gcube.portal.social.networking.ws.inputs;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Like Bean object
*/
public class LikeInputBean {
@JsonProperty("likeid")
@NotNull(message="likeid cannot be null")
@Size(message="likeid cannot be empty", min=1)
private String likeid;
@JsonProperty("postid")
@NotNull(message="postid cannot be null")
@Size(message="postid cannot be empty", min=1)
private String postid;
public LikeInputBean() {
super();
}
/**
* @param likeid
* @param postid
*/
public LikeInputBean(String likeid, String postid) {
super();
this.likeid = likeid;
this.postid = postid;
}
public String getLikeid() {
return likeid;
}
public void setLikeid(String likeid) {
this.likeid = likeid;
}
public String getPostid() {
return postid;
}
public void setPostid(String postid) {
this.postid = postid;
}
@Override
public String toString() {
return "LikeInputBean [likeid=" + likeid + ", postid=" + postid + "]";
}
}

View File

@ -1,43 +0,0 @@
package org.gcube.portal.social.networking.ws.inputs;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Application id object
*/
public class PostId {
@JsonProperty("postid")
@NotNull(message="postid cannot be null")
@Size(message="postid cannot be empty", min=1)
private String postId;
public PostId() {
super();
}
public PostId(String postId) {
super();
this.postId = postId;
}
public String getPostId() {
return postId;
}
public void setPostId(String postId) {
this.postId = postId;
}
@Override
public String toString() {
return "PostId [postid=" + postId + "]";
}
}

View File

@ -0,0 +1,53 @@
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();
}
}

View File

@ -0,0 +1,40 @@
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();
}
}

View File

@ -1,17 +1,12 @@
package org.gcube.portal.social.networking.ws.methods.v2;
import java.util.Date;
import java.util.List;
import java.util.UUID;
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;
@ -23,22 +18,12 @@ 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.Feed;
import org.gcube.portal.databook.shared.ex.FeedIDNotFoundException;
import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder;
import org.gcube.portal.social.networking.ws.inputs.CommentInputBean;
import org.gcube.portal.social.networking.ws.inputs.PostInputBean;
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.gcube.socialnetworking.socialtoken.SocialMessageParser;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.LoggerFactory;
import com.liferay.portlet.journal.FeedIdException;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
@ -46,34 +31,33 @@ import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* REST interface for the social networking library (comments).
* @author Ahmed Ibrahim ISTI-CNR
*/
@Path("2/comments")
@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 Comments {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Comments.class);
/*
* Retrieve the list of comments belonging to the post id (key) of the token in the related context
* @param key the key as in the POST JSON representation
* @param key the key as in the POST JSON representation
* @pathExample /get-comments-by-post-id?key=9ea137e9-6606-45ff-a1a2-94d4e8760583
* @return the list of comments belonging to the post identified by the key in the context identified by the token
* @return the list of comments belonging to the post identified by the key in the context identified by the token
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("get-comments-by-post-id")
@StatusCodes ({
@ResponseCode ( code = 200, condition = "The list of comments is put into the 'result' field"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 200, condition = "The list of comments is put into the 'result' field"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getAllCommentsByPostId(
@NotNull
@QueryParam("key")
@QueryParam("key")
String key) {
ResponseBean responseBean = new ResponseBean();
@ -84,7 +68,7 @@ public class Comments {
List<Comment> comments = null;
try{
logger.debug("Retrieving comments for user id " + username);
logger.info("Retrieving comments for user id " + username);
comments = CassandraConnection.getInstance().getDatabookStore().getAllCommentByPost(key);
Filters.filterCommentsPerContext(comments, context);
responseBean.setResult(comments);
@ -106,8 +90,8 @@ public class Comments {
@Produces(MediaType.APPLICATION_JSON)
@Path("get-comments-user")
@StatusCodes ({
@ResponseCode ( code = 200, condition = "The list of comments is put into the 'result' field"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 200, condition = "The list of comments is put into the 'result' field"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getCommentsUser() {
@ -119,7 +103,7 @@ public class Comments {
List<Comment> comments = null;
try{
logger.debug("Retrieving comments for user id " + username);
logger.info("Retrieving comments for user id " + username);
comments = CassandraConnection.getInstance().getDatabookStore().getRecentCommentsByUserAndDate(username, 0);
Filters.filterCommentsPerContext(comments, context);
responseBean.setResult(comments);
@ -135,16 +119,16 @@ public class Comments {
}
/*
* Retrieve comments of the token owner in the context bound to the token itself and filter them by date
* Retrieve comments of the gcube-token's owner in the context bound to the token itself and filter them by date
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("get-comments-user-by-time")
public Response getCommentsUserByTime(
@QueryParam("time")
@Min(value = 0, message="time cannot be negative")
@QueryParam("time")
@Min(value = 0, message="time cannot be negative")
long timeInMillis
) throws ValidationException{
) throws ValidationException{
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
@ -154,7 +138,7 @@ public class Comments {
List<Comment> comments = null;
try{
logger.debug("Retrieving comments for user id " + username);
logger.info("Retrieving comments for user id " + username);
comments = CassandraConnection.getInstance().getDatabookStore().getRecentCommentsByUserAndDate(username, timeInMillis);
Filters.filterCommentsPerContext(comments, context);
responseBean.setResult(comments);
@ -169,65 +153,4 @@ public class Comments {
return Response.status(status).entity(responseBean).build();
}
/**
* Create a new comment to a post having as owner the auth token's owner
* @param comment The CommentInputBean object
* @return
* @throws ValidationException
*/
@POST
@Path("comment-post")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 201, condition = "Successfull created, the new comment is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response writeComment(
@NotNull(message="Comment to write is missing")
@Valid
CommentInputBean comment) throws ValidationException {
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
logger.debug("Request of writing a comment coming from user " + username);
String context = ScopeProvider.instance.get();
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try {
String postId = comment.getPostid();
String commentText = comment.getText();
String userid = username;
Date time = new Date();
String postOwnerId = CassandraConnection.getInstance().getDatabookStore().readPost(postId).getEntityId();
Comment theComment = SocialUtils.commentPost(userid, time, postId, commentText, postOwnerId, context);
if (theComment != null)
logger.debug("Added comment " + theComment.toString());
else {
logger.error("Unable to write comment");
responseBean.setMessage("Unable to write comment, something went wrong please see server log");
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
return Response.status(status).entity(responseBean).build();
}
responseBean.setResult(theComment);
responseBean.setSuccess(true);
return Response.status(status).entity(responseBean).build();
} catch(FeedIDNotFoundException ex) {
logger.error("Unable to find a post comment", ex);
responseBean.setMessage("Could not reach the DB to write the comment, something went wrong");
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
return Response.status(status).entity(responseBean).build();
}
catch(Exception e) {
logger.error("Unable to write comment", e);
responseBean.setMessage("Could not reach the DB to write the comment, something went wrong");
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
return Response.status(status).entity(responseBean).build();
}
}
}

View File

@ -1,13 +1,10 @@
package org.gcube.portal.social.networking.ws.methods.v2;
import java.util.List;
import java.util.Map;
import javax.validation.Valid;
import javax.validation.ValidationException;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.ws.rs.*;
import javax.ws.rs.GET;
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;
@ -16,7 +13,6 @@ 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.server.DatabookStore;
import org.gcube.portal.databook.shared.Post;
import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder;
import org.gcube.portal.social.networking.ws.outputs.ResponseBean;
import org.gcube.portal.social.networking.ws.utils.CassandraConnection;
@ -30,13 +26,12 @@ import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* REST interface for the social networking library (hash tags).
* @author Ahmed Ibrahim ISTI-CNR
*/
@Path("2/hashtags")
@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 HashTags {
// Logger
@ -46,8 +41,8 @@ public class HashTags {
@Path("get-hashtags-and-occurrences/")
@Produces({MediaType.APPLICATION_JSON})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Hashtags and occurrences retrieved, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 200, condition = "Hashtags and occurrences retrieved, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
/**
* @return hashtags in the context bound to the auth token
@ -60,7 +55,7 @@ public class HashTags {
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
logger.debug("User " + username + " has requested hashtags of context " + context);
logger.info("User " + username + " has requested hashtags of context " + context);
try{
DatabookStore datastore = CassandraConnection.getInstance().getDatabookStore();
@ -81,4 +76,5 @@ public class HashTags {
return Response.status(status).entity(responseBean).build();
}
}

View File

@ -3,12 +3,10 @@ package org.gcube.portal.social.networking.ws.methods.v2;
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;
@ -20,12 +18,10 @@ 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.Like;
import org.gcube.portal.social.networking.ws.inputs.LikeInputBean;
import org.gcube.portal.social.networking.ws.inputs.PostId;
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.SocialUtils;
import org.gcube.portal.social.networking.ws.utils.Filters;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
@ -35,34 +31,33 @@ import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* REST interface for the social networking library (likes).
* @author Ahmed Ibrahim ISTI-CNR
*/
@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
* @param key the key as in the POST JSON representation
* @pathExample /get-likes-by-post-id?key=9ea137e9-6606-45ff-a1a2-94d4e8760583
* @return the list of likes belonging to the post identified by the key in the context identified by the token
* @return the list of likes belonging to the post identified by the key in the context identified by the token
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("get-likes-by-post-id")
@StatusCodes ({
@ResponseCode ( code = 200, condition = "The list of likes is put into the 'result' field"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 200, condition = "The list of likes is put into the 'result' field"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getAllLikesByPostId(
@NotNull
@QueryParam("key")
@QueryParam("key")
String key) {
ResponseBean responseBean = new ResponseBean();
@ -73,7 +68,7 @@ public class Likes {
List<Like> likes = null;
try{
logger.debug("Retrieving likes for user id " + username);
logger.info("Retrieving comments for user id " + username);
likes = CassandraConnection.getInstance().getDatabookStore().getAllLikesByPost(key);
responseBean.setResult(likes);
responseBean.setSuccess(true);
@ -86,83 +81,4 @@ 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
PostId post) 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, post.getPostId(), context);
if (likeResultOperation)
logger.debug("Added like OK to postId " + post.getPostId());
else {
logger.error("Unable to like this post"+ post.getPostId());
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
LikeInputBean likeInputBean) 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, likeInputBean.getLikeid(), likeInputBean.getPostid());
if (likeResultOperation)
logger.debug("Unlike OK to postId " + likeInputBean.getPostid());
else {
logger.error("Unable to unlike this post"+ likeInputBean.getPostid());
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();
}
}

View File

@ -122,7 +122,7 @@ public class Messages {
String body = input.getBody();
String subject = input.getSubject();
List<Recipient> recipientsIds = input.getRecipients(); // "recipients":[{"recipient":"id recipient"}, ......]
logger.debug("Sender is going to be [" + fullName + "]");
logger.info("Sender is going to be [" + fullName + "]");
// get the recipients ids (simple check, trim)
List<String> recipientsListFiltered = new ArrayList<String>();
@ -195,7 +195,7 @@ public class Messages {
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
logger.debug("Request for retrieving sent messages by " + username);
logger.info("Request for retrieving sent messages by " + username);
try{
MessageManagerClient client = AbstractPlugin.messages().build();
@ -231,7 +231,7 @@ public class Messages {
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
logger.debug("Request for retrieving received messages by " + username);
logger.info("Request for retrieving received messages by " + username);
try{
MessageManagerClient client = AbstractPlugin.messages().build();
List<Message> getMessages =client.getReceivedMessages();
@ -277,7 +277,7 @@ public class Messages {
MessageManagerClient client = AbstractPlugin.messages().build();
client.setRead(messageId, read);
String toReturn = "set Message id:" + messageId + (read ? " read" : " unread");
logger.debug("set Message id:" + messageId + " read?" + read + " for " + opExecutor);
logger.info("set Message id:" + messageId + " read?" + read + " for " + opExecutor);
responseBean.setSuccess(true);
responseBean.setResult(toReturn);

View File

@ -1,15 +1,20 @@
package org.gcube.portal.social.networking.ws.methods.v2;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import javax.validation.Valid;
import javax.validation.ValidationException;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
@ -23,6 +28,7 @@ import javax.ws.rs.core.Response.Status;
import org.gcube.applicationsupportlayer.social.ApplicationNotificationsManager;
import org.gcube.applicationsupportlayer.social.NotificationsManager;
import org.gcube.applicationsupportlayer.social.ScopeBeanExt;
import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingSite;
import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingUser;
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
@ -32,7 +38,6 @@ import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.portal.databook.shared.Notification;
import org.gcube.portal.databook.shared.NotificationChannelType;
import org.gcube.portal.databook.shared.NotificationType;
import org.gcube.portal.databook.shared.RunningJob;
import org.gcube.portal.notifications.bean.GenericItemBean;
@ -43,15 +48,20 @@ import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder;
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.mappers.CatalogueEventTypeMapper;
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.DistributedCacheClient;
import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
import org.gcube.portal.social.networking.ws.utils.SocialUtils;
import org.gcube.portal.social.networking.ws.utils.TokensUtils;
import org.gcube.social_networking.socialnetworking.model.beans.JobNotificationBean;
import org.gcube.social_networking.socialnetworking.model.beans.catalogue.CatalogueEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.WorkspaceEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.AddedItemEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.DeletedItemEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.FolderAddedUserEvent;
@ -62,28 +72,31 @@ import org.gcube.social_networking.socialnetworking.model.beans.workspace.Rename
import org.gcube.social_networking.socialnetworking.model.beans.workspace.SharedFolderEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.UnsharedFolderEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.UpdatedItemEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.WorkspaceEvent;
import org.gcube.vomanagement.usermanagement.GroupManager;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.exception.GroupRetrievalFault;
import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException;
import org.gcube.vomanagement.usermanagement.exception.UserRetrievalFault;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.mortbay.log.Log;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonProperty;
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;
import net.spy.memcached.MemcachedClient;
import net.spy.memcached.internal.OperationFuture;
/**
* REST interface for the social networking library (notifications).
* @author Ahmed Ibrahim ISTI-CNR
*/
@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")
@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 {
@ -102,15 +115,15 @@ public class Notifications {
@Path("get-range-notifications/")
@Produces(MediaType.APPLICATION_JSON)
@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)
@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")
@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")
@DefaultValue("10") @QueryParam("quantity") @Min(value=0, message="quantity must be greater or equal to 0")
int quantity
) throws ValidationException{
) throws ValidationException{
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
@ -143,19 +156,19 @@ public class Notifications {
* @responseExample application/json { "success": true, "message": null "result": true }
* @param username the username you want to check
* @return true if the notification for the user are disabled (Catalogue and Workspace ones)
*
*
*/
@GET
@Path("is-user-disabled/")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "true if the notification for the username given as query param are disabled (Catalogue and Workspace ones), false otherwise"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 200, condition = "true if the notification for the username given as query param are disabled (Catalogue and Workspace ones), false otherwise"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=AuthException.class)
public Response isUserDisabled(
@QueryParam("username") @NotNull(message="username cannot be null")
@QueryParam("username") @NotNull(message="username cannot be null")
String username) throws ValidationException{
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
@ -174,98 +187,91 @@ public class Notifications {
return Response.status(status).entity(responseBean).build();
}
// /**
// * Set user notification enabled or disabled
// * @param disable true if you want to disable the notifications for this user, false if you want to enable them
// * @return the result of the operation
// * @throws ValidationException
// */
// @POST
// @Path("set-user-notifications/")
// @Consumes(MediaType.APPLICATION_JSON)
// @Produces(MediaType.APPLICATION_JSON)
// @StatusCodes ({
// @ResponseCode ( code = 200, condition = "Notification set Off or On correctly executed"),
// @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
// })
// @AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=AuthException.class)
// public Response setUserNotifications(
// @NotNull(message="input is missing")
// @Valid
// UserSetNotificationBean setting) throws ValidationException{
//
// Caller caller = AuthorizationProvider.instance.get();
// String context = ScopeProvider.instance.get();
// ResponseBean responseBean = new ResponseBean();
// Status status = Status.OK;
//
//
// try{
// String opExecutor = caller.getClient().getId();
// Boolean result = setUserNotificationsOnOff(setting.getUsername(), setting.isDisableNotification(), opExecutor);
// String toReturn = "Could not set notifications";
// if (result) {
// toReturn = "Notifications have been set";
// toReturn += setting.isDisableNotification() ? " OFF (for 29 days unless re-enabled manually) ": " ON ";
// toReturn += "for username=" + setting.getUsername();
// }
// responseBean.setSuccess(true);
// responseBean.setResult(toReturn);
//
// } catch(Exception e){
// logger.error("Unable to set user notification", e);
// responseBean.setSuccess(false);
// responseBean.setMessage(e.getMessage());
// status = Status.INTERNAL_SERVER_ERROR;
// }
//
//
// return Response.status(status).entity(responseBean).build();
// }
/**
* Set user notification enabled or disabled
* @param disable true if you want to disable the notifications for this user, false if you want to enable them
* @return the result of the operation
* @throws ValidationException
*/
@POST
@Path("set-user-notifications/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Notification set Off or On correctly executed"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=AuthException.class)
public Response setUserNotifications(
@NotNull(message="input is missing")
@Valid
UserSetNotificationBean setting) throws ValidationException{
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try{
String opExecutor = caller.getClient().getId();
Boolean result = setUserNotificationsOnOff(setting.getUsername(), setting.isDisableNotification(), opExecutor);
String toReturn = "Could not set notifications";
if (result) {
toReturn = "Notifications have been set";
toReturn += setting.isDisableNotification() ? " OFF (for 29 days unless re-enabled manually) ": " ON ";
toReturn += "for username=" + setting.getUsername();
}
responseBean.setSuccess(true);
responseBean.setResult(toReturn);
} catch(Exception e){
logger.error("Unable to set user notification", e);
responseBean.setSuccess(false);
responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
/**
* @deprecated
*
* @param usernameToCheck
* @return true if notification are enabled for this user
* @throws IOException
*/
private boolean isNotificationEnabled(String usernameToCheck) throws IOException {
// MemcachedClient entries = new DistributedCacheClient().getMemcachedClient();
// String key = SocialUtils.DISABLED_USERS_NOTIFICATIONS_NAMESPACE+usernameToCheck;
// Boolean userEnabled = false;
// if(entries.get(key) == null)
// userEnabled = true;
// entries.getConnection().shutdown();
// return userEnabled;
return true;
private boolean isNotificationEnabled(String usernameToCheck) {
MemcachedClient entries = new DistributedCacheClient().getMemcachedClient();
String key = SocialUtils.DISABLED_USERS_NOTIFICATIONS_NAMESPACE+usernameToCheck;
Boolean userEnabled = false;
if(entries.get(key) == null)
userEnabled = true;
return userEnabled;
}
/**
*
* @param username the user you want to disable or enable notifications (max 29 days)
* @param callerId the username or clientid of the operation executor
* @param disable true if you want to disable the notifications for this user
* @return true if the operation was performed
*/
private Boolean setUserNotificationsOnOff(String username, boolean disable, String callerId) {
MemcachedClient entries = new DistributedCacheClient().getMemcachedClient();
String key = SocialUtils.DISABLED_USERS_NOTIFICATIONS_NAMESPACE+username;
OperationFuture<Boolean> result = null;
if (disable) {
result = entries.set(key, SocialUtils.CACHING_TIME_TO_EXPIRATION, "op.ex:" + callerId); //operator executor is who silenced the user
} else {
result = entries.delete(key);
}
try {
return result.getStatus().isSuccess();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// /**
// *
// * @param username the user you want to disable or enable notifications (max 29 days)
// * @param callerId the username or clientid of the operation executor
// * @param disable true if you want to disable the notifications for this user
// * @return true if the operation was performed
// * @throws IOException
// */
// private Boolean setUserNotificationsOnOff(String username, boolean disable, String callerId) throws IOException {
// MemcachedClient entries = new DistributedCacheClient().getMemcachedClient();
// String key = SocialUtils.DISABLED_USERS_NOTIFICATIONS_NAMESPACE+username;
// OperationFuture<Boolean> result = null;
// if (disable) {
// result = entries.set(key, SocialUtils.CACHING_TIME_TO_EXPIRATION, "op.ex:" + callerId); //operator executor is who silenced the user
// } else {
// result = entries.delete(key);
// }
// try {
// boolean res = result.getStatus().isSuccess();
// entries.getConnection().shutdown();
// return res;
// } catch (Exception e) {
// entries.getConnection().shutdown();
// e.printStackTrace();
// }
// return null;
// }
/**
* Send a JOB notification to a given recipient
@ -278,12 +284,12 @@ public class Notifications {
@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)
@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
@NotNull(message="input is missing")
@Valid
JobNotificationBean job) throws ValidationException{
Caller caller = AuthorizationProvider.instance.get();
@ -292,7 +298,7 @@ public class Notifications {
Status status = Status.OK;
String appQualifier = caller.getClient().getId();
logger.debug("Received request from app " + appQualifier + " to notify job status described by bean " + job);
logger.info("Received request from app " + appQualifier + " to notify job status described by bean " + job);
try{
@ -334,12 +340,12 @@ public class Notifications {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Catalogue Notification is sent correctly"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 200, condition = "Catalogue Notification is sent correctly"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response catalogue(
@NotNull(message="input is missing")
@Valid
@NotNull(message="input is missing")
@Valid
CatalogueEvent event) throws ValidationException, UserManagementSystemException, UserRetrievalFault{
Caller caller = AuthorizationProvider.instance.get();
@ -355,14 +361,14 @@ public class Notifications {
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);
senderUser = um.getUserByUsername(username);
user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), fullName, senderUser.getUserAvatarURL());
}else{
username = caller.getClient().getId();
senderUser = um.getUserByUsername(username);
senderUser = um.getUserByUsername(username);
user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), senderUser.getFullname(), senderUser.getUserAvatarURL());
}
}
String context = ScopeProvider.instance.get();
logger.debug("catalogue notifications from user = " + username);
@ -370,13 +376,11 @@ public class Notifications {
Status status = Status.OK;
boolean deliveryResult = false;
try {
//logger.debug("catalogue notifications type is " + event.getType());
logger.debug("catalogue notifications type is " + event.getType());
SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(context);
//logger.debug("social networking site is " + site.getName());
//logger.debug("context is " + context);
//logger.debug("user is " + user.getUsername());
NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, context, user);
NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, context, user);
String[] idsToNotify = event.getIdsToNotify();
if (! event.idsAsGroup()) {
@ -385,7 +389,7 @@ public class Notifications {
if (isNotificationEnabled(userIdToNotify)) {
String username2Notify = null;
try {
username2Notify = um.getUserByUsername(userIdToNotify).getUsername();
username2Notify = um.getUserByUsername(userIdToNotify).getUsername();
}
catch (Exception e) {
status = Status.BAD_REQUEST;
@ -394,20 +398,15 @@ public class Notifications {
responseBean.setMessage("Username not found, got: " + userIdToNotify);
return Response.status(status).entity(responseBean).build();
}
//logger.debug("username2notify " + username2Notify);
//logger.debug("type is " + CatalogueEventTypeMapper.getType(event.getType()));
//logger.debug("item id is " + event.getItemId());
//logger.debug("item text is " + event.getNotifyText());
//logger.debug("item url is " + event.getItemURL());
deliveryResult =
deliveryResult =
nm.notifyCatalogueEvent(
CatalogueEventTypeMapper.getType(event.getType()),
username2Notify,
event.getItemId(),
event.getNotifyText(),
CatalogueEventTypeMapper.getType(event.getType()),
username2Notify,
event.getItemId(),
event.getNotifyText(),
event.getItemURL());
}
}
else {
Log.info("Notification disabled (admin) for user "+userIdToNotify + " will not notify");
}
@ -428,20 +427,20 @@ public class Notifications {
String[] userIdsToNotify = getUsernamesByContext(scope).toArray(new String[0]); //resolve the members
for (int j = 0; j < userIdsToNotify.length; j++) {
String userIdToNotify = userIdsToNotify[j];
if (isNotificationEnabled(userIdToNotify)) {
deliveryResult =
if (isNotificationEnabled(userIdToNotify)) {
deliveryResult =
nm.notifyCatalogueEvent(
CatalogueEventTypeMapper.getType(event.getType()),
userIdToNotify,
event.getItemId(),
event.getNotifyText(),
CatalogueEventTypeMapper.getType(event.getType()),
userIdToNotify,
event.getItemId(),
event.getNotifyText(),
event.getItemURL());
} else {
Log.info("Notification disabled (admin) for user "+userIdToNotify + " will not notify");
}
}
}
}
}
catch(IllegalArgumentException e) {
status = Status.BAD_REQUEST;
logger.error("Context not valid", e);
@ -481,12 +480,12 @@ public class Notifications {
@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)
@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
@NotNull(message="input is missing")
@Valid
WorkspaceEvent event) throws ValidationException{
Caller caller = AuthorizationProvider.instance.get();
@ -510,23 +509,23 @@ public class Notifications {
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);
senderUser = um.getUserByUsername(username);
user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), fullName, senderUser.getUserAvatarURL());
}else{
username = caller.getClient().getId();
senderUser = um.getUserByUsername(username);
senderUser = um.getUserByUsername(username);
user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), senderUser.getFullname(), senderUser.getUserAvatarURL());
}
NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, context, user);
}
NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, context, user);
String[] idsToNotify = event.getIdsToNotify();
if (! event.idsAsGroup()) {
for (int i = 0; i < idsToNotify.length; i++) {
String userIdToNotify = idsToNotify[i];
if (isNotificationEnabled(userIdToNotify)) {
if (isNotificationEnabled(userIdToNotify)) {
String username2Notify = "";
try {
username2Notify = um.getUserByUsername(userIdToNotify).getUsername();
username2Notify = um.getUserByUsername(userIdToNotify).getUsername();
}
catch (Exception e) {
status = Status.NOT_ACCEPTABLE;
@ -556,14 +555,14 @@ public class Notifications {
String[] userIdsToNotify = getUsernamesByContext(scope).toArray(new String[0]); //resolve the members
for (int j = 0; j < userIdsToNotify.length; j++) {
String userIdToNotify = userIdsToNotify[j];
if (isNotificationEnabled(userIdToNotify))
if (isNotificationEnabled(userIdToNotify))
deliveryResult = notifyWorkspaceEvent(event, nm, userIdToNotify);
else {
Log.info("Notification disabled (admin) for user "+userIdToNotify + " will not notify");
}
}
}
}
}
catch(IllegalArgumentException e) {
status = Status.BAD_REQUEST;
logger.error("Context not valid", e);
@ -592,7 +591,7 @@ public class Notifications {
return Response.status(status).entity(responseBean).build();
}
/**
*
*
* @param event
* @param nm
* @param idToNotify
@ -601,49 +600,49 @@ public class Notifications {
private boolean notifyWorkspaceEvent(WorkspaceEvent event, NotificationsManager nm, String idToNotify) {
try {
switch (event.getType()) {
case ITEM_NEW: {
AddedItemEvent itemBean = (AddedItemEvent) event;
return nm.notifyAddedItem(idToNotify, WorkspaceItemMapper.getFileItem(itemBean.getItem()), WorkspaceItemMapper.getSharedFolder(itemBean.getItem().getParent()));
}
case ITEM_UPDATE: {
UpdatedItemEvent itemBean = (UpdatedItemEvent) event;
return nm.notifyUpdatedItem(idToNotify, WorkspaceItemMapper.getFileItem(itemBean.getItem()), WorkspaceItemMapper.getSharedFolder(itemBean.getItem().getParent()));
}
case ITEM_DELETE: {
DeletedItemEvent itemBean = (DeletedItemEvent) event;
return nm.notifyRemovedItem(idToNotify, itemBean.getItemName(), WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()));
}
case FOLDER_SHARE: {
SharedFolderEvent itemBean = (SharedFolderEvent) event;
return nm.notifyFolderSharing(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()));
}
case FOLDER_UNSHARE: {
UnsharedFolderEvent itemBean = (UnsharedFolderEvent) event;
return nm.notifyFolderUnsharing(idToNotify, itemBean.getUnsharedFolderId(), itemBean.getUnsharedFolderName());
}
case FOLDER_RENAME: {
RenamedFolderEvent itemBean = (RenamedFolderEvent) event;
return nm.notifyFolderRenaming(idToNotify, itemBean.getPreviousName(), itemBean.getNewName(), itemBean.getRenamedFolderId());
}
case FOLDER_ADMIN_UPGRADE: {
FolderAdminUpgradeEvent itemBean = (FolderAdminUpgradeEvent) event;
return nm.notifyAdministratorUpgrade(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()));
}
case FOLDER_ADMIN_DOWNGRADE: {
FolderAdminDowngradeEvent itemBean = (FolderAdminDowngradeEvent) event;
return nm.notifyAdministratorDowngrade(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()));
}
case FOLDER_ADDEDUSER: {
FolderAddedUserEvent itemBean = (FolderAddedUserEvent) event;
UserManager userManager = UserManagerWSBuilder.getInstance().getUserManager();
return nm.notifyFolderAddedUsers(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()), itemBean.getNewAddedUserIds(), userManager);
}
case FOLDER_REMOVEDUSER: {
FolderRemovedUserEvent itemBean = (FolderRemovedUserEvent) event;
return nm.notifyFolderRemovedUser(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()));
}
default:
break;
case ITEM_NEW: {
AddedItemEvent itemBean = (AddedItemEvent) event;
return nm.notifyAddedItem(idToNotify, WorkspaceItemMapper.getFileItem(itemBean.getItem()), WorkspaceItemMapper.getSharedFolder(itemBean.getItem().getParent()));
}
case ITEM_UPDATE: {
UpdatedItemEvent itemBean = (UpdatedItemEvent) event;
return nm.notifyUpdatedItem(idToNotify, WorkspaceItemMapper.getFileItem(itemBean.getItem()), WorkspaceItemMapper.getSharedFolder(itemBean.getItem().getParent()));
}
case ITEM_DELETE: {
DeletedItemEvent itemBean = (DeletedItemEvent) event;
return nm.notifyRemovedItem(idToNotify, itemBean.getItemName(), WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()));
}
case FOLDER_SHARE: {
SharedFolderEvent itemBean = (SharedFolderEvent) event;
return nm.notifyFolderSharing(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()));
}
case FOLDER_UNSHARE: {
UnsharedFolderEvent itemBean = (UnsharedFolderEvent) event;
return nm.notifyFolderUnsharing(idToNotify, itemBean.getUnsharedFolderId(), itemBean.getUnsharedFolderName());
}
case FOLDER_RENAME: {
RenamedFolderEvent itemBean = (RenamedFolderEvent) event;
return nm.notifyFolderRenaming(idToNotify, itemBean.getPreviousName(), itemBean.getNewName(), itemBean.getRenamedFolderId());
}
case FOLDER_ADMIN_UPGRADE: {
FolderAdminUpgradeEvent itemBean = (FolderAdminUpgradeEvent) event;
return nm.notifyAdministratorUpgrade(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()));
}
case FOLDER_ADMIN_DOWNGRADE: {
FolderAdminDowngradeEvent itemBean = (FolderAdminDowngradeEvent) event;
return nm.notifyAdministratorDowngrade(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()));
}
case FOLDER_ADDEDUSER: {
FolderAddedUserEvent itemBean = (FolderAddedUserEvent) event;
UserManager userManager = UserManagerWSBuilder.getInstance().getUserManager();
return nm.notifyFolderAddedUsers(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()), itemBean.getNewAddedUserIds(), userManager);
}
case FOLDER_REMOVEDUSER: {
FolderRemovedUserEvent itemBean = (FolderRemovedUserEvent) event;
return nm.notifyFolderRemovedUser(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()));
}
default:
break;
}
} catch(Exception e){
logger.error("Unable to send job notification", e);
@ -652,7 +651,7 @@ public class Notifications {
return false;
}
/**
*
*
* @param context
* @return
* @throws Exception
@ -681,4 +680,5 @@ public class Notifications {
}
return usernames;
}
}

View File

@ -3,7 +3,6 @@ package org.gcube.portal.social.networking.ws.methods.v2;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.validation.Valid;
import javax.validation.ValidationException;
@ -19,15 +18,16 @@ 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.portal.databook.shared.PostWithAttachment;
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.server.DatabookStore;
import org.gcube.portal.databook.shared.*;
import org.gcube.portal.databook.shared.ApplicationProfile;
import org.gcube.portal.databook.shared.Feed;
import org.gcube.portal.databook.shared.Post;
import org.gcube.portal.databook.shared.RangePosts;
import org.gcube.portal.databook.shared.ex.ColumnNameNotFoundException;
import org.gcube.portal.databook.shared.ex.FeedIDNotFoundException;
import org.gcube.portal.databook.shared.ex.FeedTypeNotFoundException;
import org.gcube.portal.databook.shared.ex.PrivacyLevelTypeNotFoundException;
import org.gcube.portal.social.networking.ws.inputs.PostInputBean;
@ -45,18 +45,17 @@ import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* REST interface for the social networking library (posts).
* @author Ahmed Ibrahim ISTI-CNR
*/
@Path("2/posts")
@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 Posts {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Posts.class);
/**
* Retrieve posts of the auth token's owner, and allow to filter them by time"
* @param timeInMillis The reference time since when retrieving posts
@ -67,13 +66,13 @@ public class Posts {
@Path("get-posts-user-since/")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successful retrieval of posts, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 200, condition = "Successful retrieval of posts, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getRecentPostsByUserAndDate(
@QueryParam("time") @Min(value = 0, message="time cannot be negative")
@QueryParam("time") @Min(value = 0, message="time cannot be negative")
long timeInMillis
) throws ValidationException{
) throws ValidationException{
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
@ -83,7 +82,7 @@ public class Posts {
List<Post> posts = null;
try{
logger.debug("Retrieving post for user id " + username + " and reference time " + timeInMillis);
logger.info("Retrieving post for user id " + username + " and reference time " + timeInMillis);
posts = CassandraConnection.getInstance().getDatabookStore().getRecentPostsByUserAndDate(username, timeInMillis);
Filters.filterPostsPerContext(posts, context);
Filters.hideSensitiveInformation(posts, caller.getClient().getId());
@ -100,8 +99,8 @@ public class Posts {
return Response.status(status).entity(responseBean).build();
}
/**
* Retrieve all user's posts
* @return all posts of the auth token's owner in the context identified by the token
@ -110,8 +109,8 @@ public class Posts {
@Path("get-posts-user/")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successful retrieval of posts, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 200, condition = "Successful retrieval of posts, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getAllPostsByUser() {
@ -138,54 +137,7 @@ public class Posts {
return Response.status(status).entity(responseBean).build();
}
/**
* Retrieve a post by id
* @return the post if the post id belongs to a post in the context identified by the token
*/
@GET
@Path("get-post/")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successful retrieval of posts, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getPost(@QueryParam("id") String id) {
String context = ScopeProvider.instance.get();
Caller caller = AuthorizationProvider.instance.get();
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
List<Post> posts = new ArrayList<>();
try{
logger.debug("Retrieving post with id " + id);
try {
posts.add(CassandraConnection.getInstance().getDatabookStore().readPost(id));
} catch(FeedIDNotFoundException e){
responseBean.setMessage("The post with id " + id + " does not exist in context " + context);
responseBean.setSuccess(false);
return Response.status(status).entity(responseBean).build();
}
Filters.filterPostsPerContext(posts, context);
Filters.hideSensitiveInformation(posts, caller.getClient().getId());
if (posts.isEmpty()) {
responseBean.setMessage("The post with id " + id + " does not belong to this context " + context);
responseBean.setSuccess(false);
status = Status.FORBIDDEN;
return Response.status(status).entity(responseBean).build();
}
responseBean.setResult(posts.get(0));
responseBean.setMessage("");
responseBean.setSuccess(true);
}catch(Exception e){
logger.error("Unable to retrieve such post.", e);
responseBean.setMessage(e.getMessage());
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
/**
* Retrieve a given quantity of latest user's posts
* @param quantity the number of latest post to get
@ -197,13 +149,13 @@ public class Posts {
@Path("get-posts-user-quantity/")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successful retrieval of posts, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 200, condition = "Successful retrieval of posts, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getQuantityPostsByUser(
@DefaultValue("10")
@QueryParam("quantity")
@Min(value=0, message="quantity cannot be negative")
@DefaultValue("10")
@QueryParam("quantity")
@Min(value=0, message="quantity cannot be negative")
int quantity) throws ValidationException{
Caller caller = AuthorizationProvider.instance.get();
@ -239,7 +191,7 @@ public class Posts {
}
return Response.status(status).entity(responseBean).build();
}
/**
* Create a new user post having as owner the auth token's owner
* @param post The post to be written
@ -251,12 +203,12 @@ public class Posts {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 201, condition = "Successfull created, the new post is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 201, condition = "Successfull created, the new post is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response writePostUser(
@NotNull(message="Post to write is missing")
@Valid
@NotNull(message="Post to write is missing")
@Valid
PostInputBean post) throws ValidationException{
logger.debug("Request of writing a feed coming from user " + post);
@ -277,24 +229,24 @@ public class Posts {
// convert enablenotification parameter
if(enableNotification)
logger.debug("Enable notification for this user post.");
logger.info("Enable notification for this user post.");
else
logger.debug("Disable notification for this user post.");
logger.info("Disable notification for this user post.");
// try to share
logger.debug("Trying to share user post...");
Post res = SocialUtils.shareUserUpdate(
Feed res = SocialUtils.shareUserUpdate(
username,
postText,
context,
postText,
context,
previewTitle,
previewDescription,
previewHost,
previewUrl,
httpImageUrl,
httpImageUrl,
enableNotification
);
);
if(res != null){
logger.debug("Post correctly written by user " + username);
@ -311,7 +263,7 @@ public class Posts {
return Response.status(status).entity(responseBean).build();
}
/**
* Retrieve the application's posts
* @return the application (IAM Client) posts belonging to the token's owner (i.e., an application)"
@ -320,9 +272,9 @@ public class Posts {
@Path("get-posts-app/")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successfull created, the new post is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 403, condition = "\"There is no application profile with such token"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 200, condition = "Successfull created, the new post is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 403, condition = "\"There is no application profile with such token"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getAllPostsByApp() {
@ -362,7 +314,7 @@ public class Posts {
return Response.status(status).entity(responseBean).build();
}
/**
* Create a new application post having as owner-application the token's owner (the IAM Client), note that the application must be registered on the Information System
* @param post The post to be written
@ -373,13 +325,13 @@ public class Posts {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successfull created, the new post is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 403, condition = "\"There is no application profile with such token"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 200, condition = "Successfull created, the new post is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 403, condition = "\"There is no application profile with such token"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response writePostApp(
@NotNull(message="Post to write is null")
@Valid
@NotNull(message="Post to write is null")
@Valid
PostInputBean post){
Caller caller = AuthorizationProvider.instance.get();
@ -415,17 +367,17 @@ public class Posts {
else
logger.debug("Disable notification for this application post.");
// write post + notification if it is the case
Post written = SocialUtils.shareApplicationUpdate(
postText,
params,
previewTitle,
previewDescription,
httpImageUrl,
appProfile,
// write feed + notification if it is the case
Feed written = SocialUtils.shareApplicationUpdate(
postText,
params,
previewTitle,
previewDescription,
httpImageUrl,
appProfile,
caller,
enableNotification
);
);
if(written != null){
responseBean.setResult(written);
@ -441,15 +393,15 @@ public class Posts {
}
/**
*
*
* @return all the posts in the context bound to the auth token
*/
@GET
@Path("get-posts-vre/")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 201, condition = "Sccessfull retrieved posts, they are reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 201, condition = "Sccessfull retrieved posts, they are reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getAllPostsByVRE() {
@ -476,28 +428,28 @@ public class Posts {
/**
* return the most recent posts for this vre up to quantity param and the last index of the posts in the timeline
* lastReturnedPostTimelineIndex is useful to know from where to start the range the next time you ask, because there are deletions
*
*
* @param from the range start (most recent feeds for this vre) has to be greater than 0
* @param quantity the number of most recent feeds for this vre starting from "from" param
* @pathExample /get-recent-posts-vre-by-range?from=1&quantity=10
* @return a <class>RangePosts</class> containing of most recent feeds for this vre
* @throws FeedTypeNotFoundException
* @throws PrivacyLevelTypeNotFoundException
* @throws ColumnNameNotFoundException
* @throws FeedTypeNotFoundException
* @throws PrivacyLevelTypeNotFoundException
* @throws ColumnNameNotFoundException
*/
@GET
@Path("get-recent-posts-vre-by-range/")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 201, condition = "Sccessfull retrieved posts, they are reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 201, condition = "Sccessfull retrieved posts, they are reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getRecentPostsByVREAndRange(
@QueryParam("from")
@Min(value=1, message="from cannot be negative")
@QueryParam("from")
@Min(value=1, message="from cannot be negative")
int from,
@QueryParam("quantity")
@Min(value=1, message="quantity cannot be negative")
@QueryParam("quantity")
@Min(value=1, message="quantity cannot be negative")
int quantity) throws ValidationException {
String context = ScopeProvider.instance.get();
@ -531,12 +483,12 @@ public class Posts {
@Path("get-posts-by-hashtag/")
@Produces({MediaType.APPLICATION_JSON})
@StatusCodes ({
@ResponseCode ( code = 201, condition = "Sccessfull retrieved posts, they are reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 201, condition = "Sccessfull retrieved posts, they are reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getPostsByHashTags(
@QueryParam("hashtag")
@NotNull(message="hashtag cannot be missing")
@QueryParam("hashtag")
@NotNull(message="hashtag cannot be missing")
String hashtag) throws ValidationException {
Caller caller = AuthorizationProvider.instance.get();
@ -544,7 +496,7 @@ public class Posts {
String context = ScopeProvider.instance.get();
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
logger.debug("User " + username + " has requested posts containing hashtag " + hashtag + " in context " + context);
logger.info("User " + username + " has requested posts containing hashtag " + hashtag + " in context " + context);
try{
DatabookStore datastore = CassandraConnection.getInstance().getDatabookStore();
List<Post> posts = datastore.getVREPostsByHashtag(context, hashtag);
@ -558,7 +510,7 @@ public class Posts {
}
return Response.status(status).entity(responseBean).build();
}
/**
* Retrieve ids (UUID) of the liked posts by the user
* @return ids (UUID) of the liked posts by the user in the context bound to the auth token
@ -567,8 +519,8 @@ public class Posts {
@Path("get-id-liked-posts/")
@Produces({MediaType.APPLICATION_JSON})
@StatusCodes ({
@ResponseCode ( code = 201, condition = "Sccessfull retrieved ids, they are reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 201, condition = "Sccessfull retrieved ids, they are reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getAllLikedPostIdsByUser() {
@ -597,7 +549,7 @@ public class Posts {
return Response.status(status).entity(responseBean).build();
}
/**
* Retrieve posts liked by the user
* @param limit The maximum number of posts to be retrieved
@ -608,13 +560,13 @@ public class Posts {
@Path("get-liked-posts/")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successfull retrieved posts, they are reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
@ResponseCode ( code = 200, condition = "Successfull retrieved posts, they are reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getAllLikedPostsByUser(
@DefaultValue("10")
@QueryParam("limit")
@Min(message="limit cannot be negative", value = 0)
@DefaultValue("10")
@QueryParam("limit")
@Min(message="limit cannot be negative", value = 0)
int limit) throws ValidationException{
Caller caller = AuthorizationProvider.instance.get();
@ -640,63 +592,4 @@ public class Posts {
}
return Response.status(status).entity(responseBean).build();
}
//libapi
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("save-user-post-attachments-lib")
public Response saveUserPostLib(
@NotNull(message="post to add is missing")
@Valid
PostWithAttachment postWithAttachment
) throws ValidationException{
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try{
Post post = postWithAttachment.getPost();
logger.debug("Post is " + post);
List<Attachment> attachments = postWithAttachment.getAttachments();
logger.debug("Attachments are " + attachments);
boolean result = CassandraConnection.getInstance().getDatabookStore().saveUserPost(post,attachments);
responseBean.setResult(result);
responseBean.setMessage("");
responseBean.setSuccess(result);
}catch(Exception e){
logger.error("Unable to write comment.", e);
responseBean.setMessage(e.getMessage());
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("save-app-post-attachments-lib")
public Response saveAppPostLib(
@NotNull(message="post to add is missing")
@Valid
PostWithAttachment postWithAttachment
) throws ValidationException{
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try{
Post post = postWithAttachment.getPost();
List<Attachment> attachments = postWithAttachment.getAttachments();
boolean result = CassandraConnection.getInstance().getDatabookStore().saveAppPost(post,attachments);
responseBean.setResult(result);
responseBean.setMessage("");
responseBean.setSuccess(result);
}catch(Exception e){
logger.error("Unable to write comment.", e);
responseBean.setMessage(e.getMessage());
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
}

View File

@ -70,7 +70,7 @@ public class Tokens {
status = Status.FORBIDDEN;
return Response.status(status).entity(responseBean).build();
}
logger.debug("Generating token for the application with id " + appId);
logger.info("Generating token for the application with id " + appId);
// each token is related to an identifier and the context
String appToken = authorizationService().generateExternalServiceToken(appId);
responseBean.setSuccess(true);

View File

@ -24,7 +24,6 @@ import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.portal.social.networking.caches.UsersCache;
import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder;
import org.gcube.portal.social.networking.liferay.ws.KeycloakAPICredentials;
import org.gcube.portal.social.networking.liferay.ws.RoleManagerWSBuilder;
import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder;
import org.gcube.portal.social.networking.ws.outputs.ResponseBean;
@ -36,11 +35,6 @@ import org.gcube.vomanagement.usermanagement.RoleManager;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.model.GCubeRole;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.keycloak.OAuth2Constants;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.KeycloakBuilder;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
@ -53,9 +47,9 @@ import com.webcohesion.enunciate.metadata.rs.StatusCodes;
*/
@Path("2/users")
@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 Users {
// Logger
@ -141,7 +135,7 @@ public class Users {
GCubeUser user = userManager.getUserByUsername(username);
fullName = user.getFullname();
logger.debug("Found fullname " + fullName + " for user " + username);
logger.info("Found fullname " + fullName + " for user " + username);
responseBean.setResult(fullName);
responseBean.setSuccess(true);
@ -182,7 +176,7 @@ public class Users {
UserManager userManager = UserManagerWSBuilder.getInstance().getUserManager();
GCubeUser user = userManager.getUserByUsername(username);
email = user.getEmail();
logger.debug("Found email " + email + " for user " + username);
logger.info("Found email " + email + " for user " + username);
responseBean.setResult(email);
responseBean.setSuccess(true);
@ -234,7 +228,7 @@ public class Users {
}
return Response.status(status).entity(responseBean).build();
}
private static final Function<GCubeUser, UserProfileExtendedWithVerifiedEmail> GCUBE_TO_EXTENDED_PROFILE_MAP_WITH_VERIFIED_EMAIL
= new Function<GCubeUser, UserProfileExtendedWithVerifiedEmail>() {
@ -256,7 +250,7 @@ public class Users {
return profile;
}
};
/**
* @responseExample application/json {
"id": "john.smith",
@ -373,7 +367,7 @@ public class Users {
return Response.status(status).entity(responseBean).build();
}
/**
* Get the map of couples username/fullname of the users belonging to a given context
* @return the map of couples username/fullname of the users belonging to the context linked to the provided token.
@ -499,61 +493,51 @@ public class Users {
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
String context = ScopeProvider.instance.get();
KeycloakAPICredentials apiService = KeycloakAPICredentials.getSingleton();
Keycloak keycloak;
keycloak = KeycloakBuilder.builder()
.serverUrl(apiService.getServerURL())
.realm(apiService.getRealm())
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
.clientId(apiService.getClientid()) //
.clientSecret(apiService.getPassword()).build();
List<String> usernames = new ArrayList<String>();
try {
List<UserRepresentation> users = searchByRole(keycloak, apiService.getRealm(), context, roleName);
if(users != null){
for (UserRepresentation user : users) {
usernames.add(user.getUsername());
try{
GroupManager groupManager = GroupManagerWSBuilder.getInstance().getGroupManager();
RoleManager roleManager = RoleManagerWSBuilder.getInstance().getRoleManager();
long roleId = roleManager.getRoleIdByName(roleName);
if(roleId > 0){
UserManager userManager = UserManagerWSBuilder.getInstance().getUserManager();
List<GCubeUser> users = null;
long groupId = groupManager.getGroupIdFromInfrastructureScope(context);
// first check if for any reason this is a global role, then (if result is null or exception arises) check for site role
// Global role's users are retrieved much faster
try{
if(GLOBAL_ROLES_ALLOWED_BY_LOCAL_CALL_METHOD.contains(roleName)){
// TODO inconsistent value can be returned
users = userManager.listUsersByGlobalRole(roleId);
}
}catch(Exception globalExp){
logger.warn("Failed while checking for global role... trying with local one", globalExp);
}
if(users == null || users.isEmpty()){
logger.debug("User list is still null/empty, checking for local information");
users = userManager.listUsersByGroupAndRole(groupId, roleId);
}
if(users != null){
for (GCubeUser gCubeUser : users) {
usernames.add(gCubeUser.getUsername());
}
}
responseBean.setResult(usernames);
responseBean.setSuccess(true);
}else{
responseBean.setMessage("No role exists whit such a name");
status = Status.BAD_REQUEST;
}
responseBean.setResult(usernames);
responseBean.setSuccess(true);
} catch(Exception e){
logger.error("Unable to retrieve user with the requested role", e);
}catch(Exception e){
logger.error("Unable to retrieve user's usernames", e);
responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
private static List<UserRepresentation> searchByRole(Keycloak keycloak, String realmName, String context, String roleName) {
logger.debug("Searching by role: {}", roleName);
String clientIdContext = context.replace("/", "%2F") ;
List<ClientRepresentation> clients = keycloak.realm(realmName)
.clients().findByClientId(clientIdContext);
String id = "";
for (ClientRepresentation client : clients) {
logger.debug("found client ="+client.getClientId());
logger.debug("found client id="+client.getId());
id =client.getId();
}
List<UserRepresentation> users = keycloak.realm(realmName)
.clients()
.get(id).roles().get(roleName)
.getUserMembers(0, 100000);
return users;
}
@GET
@Path("user-exists")
@Produces(MediaType.APPLICATION_JSON)

View File

@ -31,7 +31,8 @@ public class ResponseBean implements Serializable {
* @param success
* @param message
* @param result
*/
* @param help
*/
public ResponseBean(boolean success, String message, Object result) {
super();
this.success = success;

View File

@ -22,9 +22,9 @@ public class CassandraConnection {
private CassandraConnection(){
ApplicationContext ctx = ContextProvider.get(); // get this info from SmartGears
logger.debug("Getting connection to cassandra");
logger.info("Getting connection to cassandra");
store = new DBCassandraAstyanaxImpl(ctx.container().configuration().infrastructure());
logger.debug("Connection to cassandra created");
logger.info("Connection to cassandra created");
}
/**

View File

@ -0,0 +1,95 @@
package org.gcube.portal.social.networking.ws.utils;
import static org.gcube.resources.discovery.icclient.ICFactory.clientFor;
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint;
import org.gcube.common.resources.gcore.utils.Group;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.resources.discovery.client.api.DiscoveryClient;
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
import org.gcube.smartgears.ContextProvider;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.slf4j.LoggerFactory;
import net.spy.memcached.KetamaConnectionFactory;
import net.spy.memcached.MemcachedClient;
/**
* @author Massimiliano Assante at ISTI-CNR
*/
public class DistributedCacheClient {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(DistributedCacheClient.class);
private static final String MEMCACHED_RESOURCE_NAME = "Memcached";
private static final String CATEGORY = "Database";
private MemcachedClient mClient;
/**
* Build the singleton instance
*/
public DistributedCacheClient(){
List<InetSocketAddress> addrs = discoverHostOfServiceEndpoint();
try {
mClient = new MemcachedClient(new KetamaConnectionFactory(), addrs);
} catch (IOException e) {
e.printStackTrace();
}
}
public MemcachedClient getMemcachedClient() {
return mClient;
}
/**
* Retrieve endpoint resoruce from IS
* @return List of InetSocketAddresses
* @throws Exception
*/
private static List<InetSocketAddress> discoverHostOfServiceEndpoint(){
String currentScope = ScopeProvider.instance.get();
ApplicationContext ctx = ContextProvider.get(); // get this info from SmartGears
String infrastructure = "/"+ctx.container().configuration().infrastructure();
ScopeProvider.instance.set(infrastructure);
List<InetSocketAddress> toReturn = new ArrayList<InetSocketAddress>();
try{
SimpleQuery query = queryFor(ServiceEndpoint.class);
query.addCondition("$resource/Profile/Name/text() eq '"+ MEMCACHED_RESOURCE_NAME +"'");
query.addCondition("$resource/Profile/Category/text() eq '"+ CATEGORY +"'");
DiscoveryClient<ServiceEndpoint> client = clientFor(ServiceEndpoint.class);
List<ServiceEndpoint> ses = client.submit(query);
if (ses.isEmpty()) {
logger.error("There is no Memcached cluster having name: " + MEMCACHED_RESOURCE_NAME + " and Category " + CATEGORY + " on root context in this infrastructure: ");
return null;
}
for (ServiceEndpoint se : ses) {
Group<AccessPoint> aps = se.profile().accessPoints();
for (AccessPoint ap : aps.asCollection()) {
String address = ap.address(); //e.g. socialnetworking-d-d4s.d4science.org:11211
String[] splits = address.split(":");
String hostname = splits[0];
int port = Integer.parseInt(splits[1]);
toReturn.add(new InetSocketAddress(hostname, port));
}
break;
}
} catch(Exception e){
logger.error("Error while retrieving hosts for the Memcached cluster having name: " + MEMCACHED_RESOURCE_NAME + " and Category " + CATEGORY + " on root context");
}finally{
ScopeProvider.instance.set(currentScope);
}
ScopeProvider.instance.set(currentScope);
return toReturn;
}
}

View File

@ -24,9 +24,9 @@ public class ElasticSearchConnection {
private ElasticSearchConnection(){
try {
ApplicationContext ctx = ContextProvider.get(); // get this info from SmartGears
logger.debug("Creating connection to Elasticsearch");
logger.info("Creating connection to Elasticsearch");
es = new ElasticSearchClientImpl(ctx.container().configuration().infrastructure());
logger.debug("Elasticsearch connection created");
logger.info("Elasticsearch connection created");
} catch (Exception e) {
logger.error("Failed to connect to elasticsearch", e);
}

View File

@ -89,7 +89,7 @@ public class Filters {
* If the initial context is the root: all feeds are returned;
* If the initial context is a VO: feeds for vres within the vo are returned;
* If the initial context is a vre: feeds of the vre are returned;
* @param feeds
* @param retrievedLikedFeeds
* @param context
* @throws Exception
*/
@ -160,7 +160,7 @@ public class Filters {
/**
* Depending on the type of object provided (e.g. Feed, Comment etc), some information are removed
* @param toClear
* @param comments
* @throws Exception
*/
public static <T> void hideSensitiveInformation(List<T> toClear, String usernameCaller){

View File

@ -6,12 +6,8 @@ import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
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;
@ -28,15 +24,11 @@ import org.gcube.common.resources.gcore.utils.XPathHelper;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.portal.databook.shared.ApplicationProfile;
import org.gcube.portal.databook.shared.Comment;
import org.gcube.portal.databook.shared.Like;
import org.gcube.portal.databook.shared.Post;
import org.gcube.portal.databook.shared.PostType;
import org.gcube.portal.databook.shared.Feed;
import org.gcube.portal.databook.shared.FeedType;
import org.gcube.portal.databook.shared.PrivacyLevel;
import org.gcube.portal.databook.shared.ex.FeedIDNotFoundException;
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.MentionNotificationsThread;
import org.gcube.portal.notifications.thread.PostNotificationsThread;
import org.gcube.portal.social.networking.caches.SocialNetworkingSiteFinder;
@ -50,10 +42,6 @@ import org.gcube.social_networking.socialutillibrary.Utils;
import org.gcube.socialnetworking.socialtoken.SocialMessageParser;
import org.gcube.vomanagement.usermanagement.GroupManager;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.exception.TeamRetrievalFault;
import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException;
import org.gcube.vomanagement.usermanagement.exception.UserRetrievalFault;
import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
@ -62,7 +50,6 @@ import org.xml.sax.InputSource;
/**
* Utility class.
*/
@SuppressWarnings("deprecation")
public class SocialUtils {
// Logger
@ -71,7 +58,7 @@ public class SocialUtils {
public final static String NO_TEXT_FILE_SHARE = "_N0_73X7_SH4R3_";
public final static int CACHING_TIME_TO_EXPIRATION = 2506000;//29 days 6 minutes 40 seconds
public final static String DISABLED_USERS_NOTIFICATIONS_NAMESPACE = "dun:";
// name of the portlet for vre notification
public static final String NEWS_FEED_PORTLET_CLASSNAME = "org.gcube.portlets.user.newsfeed.server.NewsServiceImpl";
@ -108,14 +95,14 @@ public class SocialUtils {
/**
* Method used when an application needs to publish something.
* @param postText
* @param feedText
* @param uriParams
* @param previewTitle
* @param previewDescription
* @param httpImageUrl
* @return true upon success, false on failure
*/
public static Post shareApplicationUpdate(
public static Feed shareApplicationUpdate(
String postText,
String uriParams,
String previewTitle,
@ -135,12 +122,12 @@ public class SocialUtils {
SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(ScopeProvider.instance.get());
escapedPostText = Utils.convertMentionUsernamesAnchorHTML(escapedPostText, mentionedUsersToConvertInHTML, site.getSiteURL(), site.getSiteLandingPagePath());
logger.debug("*** Escaped post text is " + escapedPostText);
logger.info("*** Escaped post text is " + escapedPostText);
String scope = ScopeProvider.instance.get();
String appId = caller.getClient().getId();
Post toWrite =
Feed toWrite =
buildPost(
escapedPostText,
uriParams == null ? "" : uriParams,
@ -151,10 +138,10 @@ public class SocialUtils {
scope);
// try to save it
boolean res = CassandraConnection.getInstance().getDatabookStore().saveAppPost(toWrite);
boolean res = CassandraConnection.getInstance().getDatabookStore().saveAppFeed(toWrite);
if(res){
logger.debug("Feed correctly written by application " + appId);
logger.info("Feed correctly written by application " + appId);
// wait a bit before saving hashtags
if(hashtags != null && !hashtags.isEmpty())
@ -229,7 +216,7 @@ public class SocialUtils {
* @param previewThumbnailUrl the image url to show in the preview
* @return a feed instance ready to be written
*/
private static Post buildPost(
private static Feed buildPost(
String description,
String uriParams,
String previewTitle,
@ -244,9 +231,9 @@ public class SocialUtils {
if (uriParams != null && uriParams.compareTo("") != 0)
uri += "?"+uriParams;
Post toReturn = new Post(
Feed toReturn = new Feed(
UUID.randomUUID().toString(),
PostType.PUBLISH,
FeedType.PUBLISH,
applicationProfile.getKey(),
new Date(),
scopeApp,
@ -385,7 +372,7 @@ public class SocialUtils {
* @param notifyGroup
* @return The written Feed
*/
public static Post shareUserUpdate(
public static Feed shareUserUpdate(
String userId,
String postText,
String vreId,
@ -436,12 +423,12 @@ public class SocialUtils {
textToPost = escapedPostText;
}
Post toShare = new Post(UUID.randomUUID().toString(), PostType.PUBLISH, userId, new Date(),
Feed toShare = new Feed(UUID.randomUUID().toString(), FeedType.PUBLISH, userId, new Date(),
vreId, url, urlThumbnail, textToPost, PrivacyLevel.SINGLE_VRE, fullName, email, thumbnailURL, linkTitle, linkDesc, host);
logger.debug("Attempting to save Post with text: " + textToPost + " Level = " + PrivacyLevel.SINGLE_VRE + " Timeline = " + vreId);
logger.info("Attempting to save Post with text: " + textToPost + " Level = " + PrivacyLevel.SINGLE_VRE + " Timeline = " + vreId);
boolean result = CassandraConnection.getInstance().getDatabookStore().saveUserPost(toShare);
boolean result = CassandraConnection.getInstance().getDatabookStore().saveUserFeed(toShare);
if(vreId != null && vreId.compareTo("") != 0 && result) {
@ -450,7 +437,7 @@ public class SocialUtils {
try {
try{
logger.debug("Sleeping waiting for cassandra's update");
logger.info("Sleeping waiting for cassandra's update");
Thread.sleep(1000);
}catch(Exception e){
@ -508,218 +495,4 @@ public class SocialUtils {
}
return toShare;
}
/**
* Allows to comment post in a certain vre.
* @param userid the username
* @param time the date and time of the comment
* @param postId the key of the post that was commented
* @param commentText the text as it is, it will be parsed
* @param postOwnerId the username of the user who created the post that was commented
* @param context the VRE context
*
* @return the Comment instance if ok, null if somwthign went KO
* @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
ArrayList<GenericItemBean> mentionedUsers = getUsersFromUsernames(Utils.getMentionedUsernames(commentText));
ArrayList<ItemBean> mentionedUsersToConvertInHTML = convertToItemBean(mentionedUsers);
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();
try {
user = uManager.getUserByUsername(userid);
} catch(Exception e){
logger.error("Unable to get user informations, comment write fails.", e);
return null;
}
String commentKey = UUID.randomUUID().toString(); // a unique id that goes in the DB
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.debug("Attempting to save Comment with text: " + commentText + " postid="+postId);
boolean result = CassandraConnection.getInstance().getDatabookStore().addComment(theComment);
logger.debug("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)
logger.debug("The post creator is " + postOwnerId);
if (! user.getUsername().equals(postOwnerId)) {
boolean resultNotifyOwnComment = nm.notifyOwnCommentReply(postOwnerId, postId, escapedCommentText, theComment.getKey());
logger.debug("Comment Notification to post creator added? " + resultNotifyOwnComment);
}
//if there are users who liked this post they get notified, asynchronously with this thread
ArrayList<Like> 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(),
uManager, user.getUsername(), theComment.getFeedid(), escapedCommentText, nm, postOwnerId, theComment.getKey(), likes));
commentsNotificationthread.start();
//send the notification to the mentioned users, if any
if (mentionedUsers != null && mentionedUsers.size() > 0) {
ArrayList<GenericItemBean> toPass = new ArrayList<GenericItemBean>();
// among the mentionedUsers there could be groups of people
Map<String, ItemBean> uniqueUsersToNotify = new HashMap<>();
UserManager um = new LiferayUserManager();
for (ItemBean bean : mentionedUsersToConvertInHTML) {
if(bean.isItemGroup()){
// retrieve the users of this group
try {
List<GCubeUser> teamUsers = um.listUsersByTeam(Long.parseLong(bean.getId()));
for (GCubeUser userTeam : teamUsers) {
if(!uniqueUsersToNotify.containsKey(userTeam.getUsername()))
uniqueUsersToNotify.put(userTeam.getUsername(), new ItemBean(userTeam.getUserId()+"",
userTeam.getUsername(), userTeam.getFullname(), userTeam.getUserAvatarURL()));
}
} catch (NumberFormatException
| UserManagementSystemException
| TeamRetrievalFault | UserRetrievalFault e) {
logger.error("Unable to retrieve team information", e);
}
}else{
// it is a user, just add to the hashmap
if(!uniqueUsersToNotify.containsKey(bean.getName()))
uniqueUsersToNotify.put(bean.getName(), bean);
}
}
// iterate over the hashmap
Iterator<Entry<String, ItemBean>> userMapIterator = uniqueUsersToNotify.entrySet().iterator();
while (userMapIterator.hasNext()) {
Map.Entry<String, ItemBean> userEntry = (Map.Entry<String, ItemBean>) userMapIterator
.next();
ItemBean userBean = userEntry.getValue();
toPass.add(new GenericItemBean(userBean.getId(), userBean.getName(), userBean.getAlternativeName(), userBean.getThumbnailURL()));
}
Thread thread = new Thread(new MentionNotificationsThread(theComment.getFeedid(), escapedCommentText, nm, null, toPass));
thread.start();
}
return theComment;
}
private static ArrayList<Like> getAllLikesByPost(String postid) {
ArrayList<Like> toReturn = (ArrayList<Like>) CassandraConnection.getInstance().getDatabookStore().getAllLikesByPost(postid);
logger.debug("Asking likes for " + postid);
for (Like like : toReturn) {
// retrieve user information
GCubeUser user;
UserManager uManager = UserManagerWSBuilder.getInstance().getUserManager();
try {
user = uManager.getUserByUsername(like.getUserid());
} catch(Exception e){
logger.error("Unable to get user informations, comment write fails.", e);
return null;
}
String thumbnailURL = user.getUserAvatarURL();
like.setThumbnailURL(thumbnailURL == null ? "" : thumbnailURL);
}
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 {
logger.debug("Attempting to read post with id: " +postid);
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.debug("The post creator is " + postOwnerId);
if (! user.getUsername().equals(postOwnerId)) {
resultNotifyLike = nm.notifyLikedPost(postOwnerId, postid, escapedPostText);
logger.debug("Like Notification to post creator added? " + resultNotifyLike);
}
}
return likeCommitResult && resultNotifyLike;
}
public static boolean unlike(String username, String likeid, 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, likeid, postid);
} catch (Exception e) {
logger.error("Post not Found for this like ot could not unlike the post " + e.getMessage());
return false;
}
return unlikeCommitResult;
}
}

View File

@ -1,12 +1,11 @@
.d4science_intro {
top: 0;
z-index: 2000;
position: fixed;
display: block ruby;
padding: 10px;
background: white;
width: 100%;
height: 100px;
top: 0;
z-index: 2000;
position: fixed;
display: block ruby;
padding: 10px;
background: white;
width: 100%;
}
.navbar-fixed-top {