Code refactored which enable the following functions. For each request

- the requesting user role and email are retrieved via social networking
service and updated on CKAN.
This commit is contained in:
Luca Frosini 2019-09-12 14:26:24 +02:00
parent 635825ebd9
commit 4a7c0f2a70
17 changed files with 481 additions and 385 deletions

View File

@ -1,68 +0,0 @@
package org.gcube.gcat.oldutils;
import javax.cache.Cache;
import javax.cache.CacheManager;
import javax.cache.Caching;
import javax.cache.configuration.MutableConfiguration;
import javax.cache.expiry.CreatedExpiryPolicy;
import javax.cache.expiry.Duration;
import javax.cache.spi.CachingProvider;
// import org.gcube.datacatalogue.metadatadiscovery.DataCalogueMetadataFormatReader;
import com.fasterxml.jackson.databind.JsonNode;
/**
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
public class CachesManager {
// the following caches are declared within the ehcache.xml (no default is available, so pay attention)
// public static final String PROFILES_READERS_CACHE = "profile_readers";
public static final String PROFILES_USERS_CACHE = "profile_users";
private static final CacheManager cacheManager;
// private static final Cache<String, DataCalogueMetadataFormatReader> readerCache;
private static final Cache<String, JsonNode> userCache;
static {
CachingProvider provider = Caching.getCachingProvider();
cacheManager = provider.getCacheManager();
/*
MutableConfiguration<String, DataCalogueMetadataFormatReader> readerConfiguration =
new MutableConfiguration<String, DataCalogueMetadataFormatReader>()
.setTypes(String.class, DataCalogueMetadataFormatReader.class)
.setStoreByValue(false)
.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ONE_MINUTE));
readerCache = cacheManager.createCache(PROFILES_READERS_CACHE, readerConfiguration);
*/
MutableConfiguration<String, JsonNode> userConfiguration =
new MutableConfiguration<String, JsonNode>()
.setTypes(String.class, JsonNode.class)
.setStoreByValue(false)
.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ONE_MINUTE));
userCache = cacheManager.createCache(PROFILES_USERS_CACHE, userConfiguration);
}
private CachesManager() {}
/*
public static Cache<String, DataCalogueMetadataFormatReader> getReaderCache() {
return readerCache;
}
*/
public static Cache<String, JsonNode> getUserCache() {
return userCache;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
cacheManager.close();
}
}

View File

@ -31,7 +31,7 @@ import org.gcube.gcat.persistence.ckan.CKANPackage;
import org.gcube.gcat.persistence.ckan.CKANUser;
import org.gcube.gcat.persistence.ckan.CKANUtility;
import org.gcube.gcat.profile.MetadataUtility;
import org.gcube.gcat.social.SocialService;
import org.gcube.gcat.social.SocialPost;
import org.geojson.GeoJsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -93,7 +93,7 @@ public class Validator {
CustomField cf = new CustomField(object);
if(cf.getKey().equals(CKANPackage.EXTRAS_KEY_VALUE_SYSTEM_TYPE)) {
metadataTypeCF = cf;
} else if(cf.getKey().equals(SocialService.ITEM_URL)) {
} else if(cf.getKey().equals(SocialPost.ITEM_URL)) {
continue;
} else {
customFields.add(cf);
@ -263,7 +263,7 @@ public class Validator {
}
public void addUserToGroupAsSysAdmin(String groupName) throws Exception {
String username = CKANUtility.getCKANUsername();
String username = CKANUser.getCKANUsername();
addUserToGroupAsSysAdmin(groupName, username);
}

View File

@ -1,9 +1,6 @@
package org.gcube.gcat.persistence.ckan;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.util.HashMap;
@ -15,15 +12,13 @@ import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import org.gcube.common.gxhttp.request.GXHTTPStringRequest;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueFactory;
import org.gcube.gcat.utils.Constants;
import org.gcube.gcat.utils.ContextUtility;
import org.gcube.gcat.utils.HTTPUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -249,45 +244,19 @@ public abstract class CKAN {
return map;
}
protected StringBuilder getStringBuilder(InputStream inputStream) throws IOException {
StringBuilder result = new StringBuilder();
try(BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while((line = reader.readLine()) != null) {
result.append(line);
}
}
return result;
}
protected GXHTTPStringRequest getGXHTTPStringRequest(String path, boolean post) throws UnsupportedEncodingException {
String catalogueURL = dataCatalogue.getCatalogueUrl();
GXHTTPStringRequest gxhttpStringRequest = GXHTTPStringRequest.newRequest(catalogueURL);
gxhttpStringRequest.from(Constants.CATALOGUE_NAME);
if(post) {
gxhttpStringRequest.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
}
gxhttpStringRequest.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
GXHTTPStringRequest gxhttpStringRequest = HTTPUtility.createGXHTTPStringRequest(catalogueURL, path, post);
gxhttpStringRequest.isExternalCall(true);
gxhttpStringRequest.header(AUTH_CKAN_HEADER, getApiKey());
gxhttpStringRequest.path(path);
return gxhttpStringRequest;
}
protected String getResultAsString(HttpURLConnection httpURLConnection) throws IOException {
int responseCode = httpURLConnection.getResponseCode();
if(responseCode >= Status.BAD_REQUEST.getStatusCode()) {
Status status = Status.fromStatusCode(responseCode);
InputStream inputStream = httpURLConnection.getErrorStream();
StringBuilder result = getStringBuilder(inputStream);
logger.trace(result.toString());
throw new WebApplicationException(status);
}
InputStream inputStream = httpURLConnection.getInputStream();
String ret = getStringBuilder(inputStream).toString();
protected String getResultAndValidate(HttpURLConnection httpURLConnection) throws IOException {
String ret = HTTPUtility.getResultAsString(httpURLConnection);
logger.trace("Got Respose is {}", ret);
result = validateCKANResponse(ret);
if(result instanceof NullNode) {
@ -302,7 +271,7 @@ public abstract class CKAN {
GXHTTPStringRequest gxhttpStringRequest = getGXHTTPStringRequest(path, false);
gxhttpStringRequest.queryParams(parameters);
HttpURLConnection httpURLConnection = gxhttpStringRequest.get();
return getResultAsString(httpURLConnection);
return getResultAndValidate(httpURLConnection);
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {
@ -315,7 +284,7 @@ public abstract class CKAN {
logger.debug("Going to send POST request with body {}", body);
GXHTTPStringRequest gxhttpStringRequest = getGXHTTPStringRequest(path, true);
HttpURLConnection httpURLConnection = gxhttpStringRequest.post(body);
return getResultAsString(httpURLConnection);
return getResultAndValidate(httpURLConnection);
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {

View File

@ -1,18 +1,12 @@
package org.gcube.gcat.persistence.ckan;
import java.util.Map;
import java.util.Set;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.datacatalogue.ckanutillibrary.shared.RolesCkanGroupOrOrg;
import org.gcube.gcat.utils.ContextUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import eu.trentorise.opendata.jackan.model.CkanOrganization;
/**
* @author Luca Frosini (ISTI - CNR)
*/
@ -62,36 +56,16 @@ public class CKANOrganization extends CKAN {
protected static final String ORGANIZATION_PERMISSION_KEY = "permission";
protected static final String ORGANIZATION_PERMISSION_VALUE_READ = "read";
public String getUserRole(String gCubeUsername) {
Map<String,Map<CkanOrganization,RolesCkanGroupOrOrg>> rolesPerOrganization = dataCatalogue
.getUserRoleByOrganization(gCubeUsername, CKANUtility.getApiKey(gCubeUsername));
if(rolesPerOrganization.containsKey(name)) {
Map<CkanOrganization,RolesCkanGroupOrOrg> map = rolesPerOrganization.get(name);
Set<CkanOrganization> ckanOrganizations = map.keySet();
for(CkanOrganization ckanOrganization : ckanOrganizations) {
return map.get(ckanOrganization).name().toLowerCase();
}
}
return null;
}
public void addUserToOrganisation(String gCubeUsername, String role, boolean force) {
String ckanUsername = CKANUtility.getCKANUsername(gCubeUsername);
String userRole = getUserRole(gCubeUsername);
if((userRole==null || force)) {
if(userRole!=null && userRole.toLowerCase().compareTo(role.toLowerCase())==0) {
logger.debug("User {} is already member of Organisation {} with role {}", ckanUsername, name, userRole);
return;
}
ObjectNode objectNode = mapper.createObjectNode();
objectNode.put(ID_KEY, name);
objectNode.put(USERNAME_KEY, ckanUsername);
objectNode.put(ROLE_KEY, role);
sendPostRequest(ORGANIZATION_MEMBER_CREATE, getAsString(objectNode));
logger.debug("User {} successfully added to Organisation {} with role {}", ckanUsername, name, role);
}else {
logger.debug("User {} is already member of Organisation {} with role {}", ckanUsername, name, userRole);
}
public void addUserToOrganisation(String gCubeUsername, String role) {
String ckanUsername = CKANUser.getCKANUsername(gCubeUsername);
ObjectNode objectNode = mapper.createObjectNode();
objectNode.put(ID_KEY, name);
objectNode.put(USERNAME_KEY, ckanUsername);
objectNode.put(ROLE_KEY, role);
sendPostRequest(ORGANIZATION_MEMBER_CREATE, getAsString(objectNode));
logger.debug("User {} successfully added to Organisation {} with role {}", ckanUsername, name, role);
}
public static String getCKANOrganizationName() {

View File

@ -23,7 +23,7 @@ import org.gcube.gcat.annotation.PURGE;
import org.gcube.gcat.api.GCatConstants;
import org.gcube.gcat.oldutils.Validator;
import org.gcube.gcat.profile.MetadataUtility;
import org.gcube.gcat.social.SocialService;
import org.gcube.gcat.social.SocialPost;
import org.gcube.gcat.utils.ContextUtility;
import org.gcube.gcat.utils.URIResolver;
import org.slf4j.Logger;
@ -93,9 +93,7 @@ public class CKANPackage extends CKAN {
public static final String GROUPS_KEY = "groups";
public static final String TAGS_KEY = "tags";
protected SocialService socialService;
protected final List<CKANResource> managedResources;
protected String itemID;
@ -171,12 +169,12 @@ public class CKANPackage extends CKAN {
objectNode.remove(CAPACITY_KEY);
}
socialService = new SocialService();
JsonNode userJsonNode = CKANUtility.getCKANUser(false);
String ckanUsername = userJsonNode.get(CKANUser.NAME).asText();
objectNode.put(AUTHOR_KEY, ckanUsername);
objectNode.put(AUTHOR_EMAIL_KEY, userJsonNode.get(CKANUser.EMAIL).asText());
CKANUser ckanUser = CKANUser.getCurrentCKANUser();
objectNode.put(AUTHOR_KEY, ckanUser.getName());
objectNode.put(AUTHOR_EMAIL_KEY, ckanUser.getPortalUser().getEMail());
// owner organization must be specified if the token belongs to a VRE
ScopeBean scopeBean = new ScopeBean(ContextUtility.getCurrentContext());
@ -212,7 +210,7 @@ public class CKANPackage extends CKAN {
}
}
CKANUtility.addUserToOrganization(ckanUsername, gotOrganization, CKANUtility.MEMBER_ROLE, false);
ckanUser.addUserToOrganization(gotOrganization);
return objectNode;
}
@ -353,6 +351,7 @@ public class CKANPackage extends CKAN {
if(socialPost) {
ArrayNode arrayNode = (ArrayNode) result.get(TAGS_KEY);
SocialPost socialService = new SocialPost();
socialService.setItemID(itemID);
socialService.setItemURL(catalogueItemURL);
socialService.setTags(arrayNode);

View File

@ -1,9 +1,18 @@
package org.gcube.gcat.persistence.ckan;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response.Status;
import org.gcube.gcat.social.PortalUser;
import org.gcube.gcat.utils.ContextUtility;
import org.gcube.gcat.utils.RandomString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
@ -12,6 +21,8 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
*/
public class CKANUser extends CKAN {
private static final Logger logger = LoggerFactory.getLogger(CKANUser.class);
/* User Paths */
// see https://docs.ckan.org/en/latest/api/#ckan.logic.action.get.user_list
public static final String USER_LIST = CKAN.CKAN_API_PATH + "user_list";
@ -26,6 +37,86 @@ public class CKANUser extends CKAN {
public static final String ADD_USER_TO_GROUP = CKAN.CKAN_API_PATH + "member_create";
public static final String NAME = "name";
public static final String EMAIL = "email";
public static final String PASSWORD = "password";
private static final String API_KEY = "apikey";
public enum Role {
MEMBER("Catalogue-Member", "member"),
EDITOR("Catalogue-Editor", "editor"),
ADMIN("Catalogue-Admin", "admin");
private final String portalRole;
private final String ckanRole;
Role(String portalRole, String ckanRole) {
this.portalRole = portalRole;
this.ckanRole = ckanRole;
}
public String getPortalRole() {
return portalRole;
}
public String getCkanRole() {
return ckanRole;
}
protected static final Map<String, Role> ROLE_BY_PORTAL_ROLE;
protected static final Map<String, Role> ROLE_BY_CKAN_ROLE;
static {
ROLE_BY_PORTAL_ROLE = new HashMap<String, Role>();
// null or empty string identify a member
ROLE_BY_PORTAL_ROLE.put(null, MEMBER);
ROLE_BY_PORTAL_ROLE.put("", MEMBER);
ROLE_BY_CKAN_ROLE = new HashMap<String, Role>();
for(Role role : Role.values()) {
ROLE_BY_PORTAL_ROLE.put(role.getPortalRole(), role);
ROLE_BY_CKAN_ROLE.put(role.getCkanRole(), role);
}
}
public static Role getRoleFromPortalRole(String portalRole) {
return ROLE_BY_PORTAL_ROLE.get(portalRole);
}
public static String getCkanRoleFromPortalRole(String portalRole) {
return getRoleFromPortalRole(portalRole).getCkanRole();
}
public static Role getRoleFromCkanRole(String ckanRole) {
return ROLE_BY_CKAN_ROLE.get(ckanRole);
}
public static String getPortalRoleFromCkanRole(String ckanRole) {
return getRoleFromCkanRole(ckanRole).getPortalRole();
}
}
private static final InheritableThreadLocal<CKANUser> currentCkanUser = new InheritableThreadLocal<CKANUser>() {
@Override
protected CKANUser initialValue() {
CKANUser ckanUser = new CKANUser();
ckanUser.retrieve();
return ckanUser;
}
};
public static CKANUser getCurrentCKANUser() {
return currentCkanUser.get();
}
protected PortalUser portalUser;
protected Role role;
public CKANUser() {
super();
LIST = USER_LIST;
@ -37,15 +128,13 @@ public class CKANUser extends CKAN {
PURGE = null;
}
public static final String NAME = "name";
public static final String EMAIL = "email";
public static final String PASSWORD = "password";
public String create() {
RandomString randomString = new RandomString(12);
ObjectNode objectNode = mapper.createObjectNode();
objectNode.put(NAME, name);
objectNode.put(EMAIL, name+"@gcube.ckan.org");
objectNode.put(EMAIL, getPortalUser().getEMail());
objectNode.put(PASSWORD, randomString.nextString());
return create(getAsString(objectNode));
}
@ -56,6 +145,75 @@ public class CKANUser extends CKAN {
}
private void retrieve() {
setApiKey(CKANUtility.getSysAdminAPI());
try {
if(name==null || name.compareTo("")==0) {
setName(getCKANUsername());
}
read();
} catch(WebApplicationException e) {
if(e.getResponse().getStatusInfo() == Status.NOT_FOUND) {
create();
}else {
throw e;
}
}
addUserToOrganization();
}
protected void parseResult() {
name = result.get(NAME).asText();
apiKey = result.get(API_KEY).asText();
}
protected static String getCKANUsername(String username){
if(username == null)
return null;
return username.trim().replaceAll("\\.", "_");
}
public static String getCKANUsername() {
return getCKANUsername(ContextUtility.getUsername());
}
public String read() {
String ret = super.read();
parseResult();
return ret;
}
protected void addUserToOrganization(String organizationName, String ckanUsername, String role) {
logger.trace("Going to add user {} to organization {} with role {}", ckanUsername, organizationName, role);
CKANOrganization ckanOrganization = new CKANOrganization();
ckanOrganization.setApiKey(CKANUtility.getSysAdminAPI());
ckanOrganization.setName(organizationName);
ckanOrganization.addUserToOrganisation(ckanUsername, role);
}
private Role getRole() {
if(role==null) {
role = Role.MEMBER;
List<String> roles = getPortalUser().getRoles();
for(String portalRole : roles){
Role gotRole = Role.getRoleFromPortalRole(portalRole);
if(gotRole!=null && gotRole.ordinal()>role.ordinal()){
role = gotRole;
}
}
}
return role;
}
public void addUserToOrganization(String organizationName) {
addUserToOrganization(organizationName, name, getRole().getCkanRole());
}
public void addUserToOrganization() {
String organizationName = CKANOrganization.getCKANOrganizationName();
addUserToOrganization(organizationName);
}
public void addToGroup(String groupName) throws WebApplicationException {
try {
ObjectNode objectNode = mapper.createObjectNode();
@ -70,4 +228,12 @@ public class CKANUser extends CKAN {
throw new InternalServerErrorException(e);
}
}
public PortalUser getPortalUser() {
if(portalUser==null) {
portalUser = new PortalUser();
}
return portalUser;
}
}

View File

@ -1,19 +1,14 @@
package org.gcube.gcat.persistence.ckan;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response.Status;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueFactory;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueRunningCluster;
import org.gcube.datacatalogue.ckanutillibrary.server.utils.CatalogueUtilMethods;
import org.gcube.gcat.utils.ContextUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.JsonNode;
/**
* @author Luca Frosini (ISTI - CNR)
*/
@ -21,9 +16,6 @@ public class CKANUtility {
private static final Logger logger = LoggerFactory.getLogger(CKANUtility.class);
public static final String MEMBER_ROLE = "member";
private static final String API_KEY = "apikey";
public static DataCatalogue getCatalogue() throws Exception {
String context = ContextUtility.getCurrentContext();
logger.debug("Discovering ckan instance in context {}", context);
@ -40,70 +32,10 @@ public class CKANUtility {
}
}
protected static String getCKANUsername(String username) {
String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username);
return ckanUsername;
}
public static String getCKANUsername() {
return getCKANUsername(ContextUtility.getUsername());
}
public static JsonNode getCKANUser(boolean addToOrganization) {
return createCKANUser(getCKANUsername(), addToOrganization);
}
public static JsonNode getCKANUser() {
return getCKANUser(true);
}
protected static JsonNode createCKANUser(String ckanUsername, boolean addToOrganization) {
ckanUsername = CKANUtility.getCKANUsername(ckanUsername);
CKANUser ckanUser = new CKANUser();
ckanUser.setApiKey(getSysAdminAPI());
public static String getApiKey() {
try {
ckanUser.setName(ckanUsername);
ckanUser.read();
} catch(WebApplicationException e) {
if(e.getResponse().getStatusInfo() == Status.NOT_FOUND) {
ckanUser.setName(ckanUsername);
ckanUser.create();
}else {
throw e;
}
}
JsonNode jsonNode = ckanUser.getJsonNodeResult();
if(addToOrganization) {
addUserToOrganization(ckanUsername, MEMBER_ROLE, false);
}
return jsonNode;
}
public static void addUserToOrganization(String ckanUsername, String organizationName, String role, boolean force) {
CKANOrganization ckanOrganization = new CKANOrganization();
ckanOrganization.setApiKey(getSysAdminAPI());
ckanOrganization.setName(organizationName);
ckanOrganization.addUserToOrganisation(ckanUsername, role, force);
}
protected static void addUserToOrganization(String ckanUsername, String role, boolean force) {
String organizationName = CKANOrganization.getCKANOrganizationName();
addUserToOrganization(ckanUsername, organizationName, role, force);
}
public static String getApiKey() throws Exception {
String ckanUsername = getCKANUsername();
return getApiKey(ckanUsername);
}
protected static String getApiKey(String ckanUsername) {
try {
String apiKey = getCatalogue().getApiKeyFromUsername(ckanUsername);
if(apiKey == null) {
JsonNode jsonNode = createCKANUser(ckanUsername, true);
apiKey = jsonNode.get(API_KEY).asText();
}
return apiKey;
CKANUser ckanUser = CKANUser.getCurrentCKANUser();
return ckanUser.getApiKey();
}catch (Exception e) {
throw new InternalServerErrorException(e);
}

View File

@ -0,0 +1,125 @@
package org.gcube.gcat.social;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.ws.rs.InternalServerErrorException;
import org.gcube.common.gxhttp.request.GXHTTPStringRequest;
import org.gcube.gcat.utils.HTTPUtility;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
public class PortalUser {
protected static final String RESPONSE_SUCCESS_KEY = "success";
protected static final String RESPONSE_MESSAGE_KEY = "message";
protected static final String RESPONSE_RESULT_KEY = "result";
// https://wiki.gcube-system.org/gcube/Social_Networking_Service
// private static final String SOCIAL_SERVICE_GET_GCUBE_USER_PROFILE_PATH = "2/users/get-profile";
protected static final String SOCIAL_SERVICE_GET_OAUTH_USER_PROFILE_PATH = "2/users/get-oauth-profile";
// This key cotnains the fullname
protected static final String OAUTH_USER_PROFILE_NAME_KEY = "name";
protected static final String OAUTH_USER_PROFILE_EMAIL_KEY = "email";
protected static final String OAUTH_USER_PROFILE_ROLES_KEY = "roles";
protected final ObjectMapper objectMapper;
// private JsonNode gCubeUserProfile;
protected JsonNode oAuthUserProfile;
protected String fullName;
protected String eMail;
protected List<String> roles;
public PortalUser() {
this.objectMapper = new ObjectMapper();
}
/*
private JsonNode validateGCubeUserProfileResponse(JsonNode jsonNode) {
if(jsonNode.get(RESPONSE_SUCCESS_KEY).asBoolean()) {
return jsonNode.get(RESPONSE_RESULT_KEY);
} else {
String message = jsonNode.get(RESPONSE_MESSAGE_KEY).asText();
throw new InternalServerErrorException(message);
}
}
private JsonNode getGCubeUserProfile() throws Exception {
if(gCubeUserProfile == null) {
String socialServiceBasePath = SocialServiceDiscovery.getCurrentScopeSocialServiceBasePath();
GXHTTPStringRequest gxhttpStringRequest = HTTPUtility.createGXHTTPStringRequest(socialServiceBasePath,
SOCIAL_SERVICE_GET_GCUBE_USER_PROFILE_PATH, false);
HttpURLConnection httpURLConnection = gxhttpStringRequest.get();
String ret = HTTPUtility.getResultAsString(httpURLConnection);
JsonNode jsonNode = objectMapper.readTree(ret);
gCubeUserProfile = validateGCubeUserProfileResponse(jsonNode);
}
return gCubeUserProfile;
}
*/
public JsonNode getOAuthUserProfile() {
if(oAuthUserProfile == null) {
try {
String socialServiceBasePath = SocialServiceDiscovery.getCurrentScopeSocialServiceBasePath();
GXHTTPStringRequest gxhttpStringRequest = HTTPUtility.createGXHTTPStringRequest(socialServiceBasePath,
SOCIAL_SERVICE_GET_OAUTH_USER_PROFILE_PATH, false);
HttpURLConnection httpURLConnection = gxhttpStringRequest.get();
String ret = HTTPUtility.getResultAsString(httpURLConnection);
oAuthUserProfile = objectMapper.readTree(ret);
}catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
return oAuthUserProfile;
}
public String getFullName() {
if(fullName == null) {
fullName = getOAuthUserProfile().get(OAUTH_USER_PROFILE_NAME_KEY).asText();
}
return fullName;
}
public String getEMail() {
if(eMail == null) {
eMail = getOAuthUserProfile().get(OAUTH_USER_PROFILE_EMAIL_KEY).asText();
}
return eMail;
}
public List<String> getRoles() {
if(roles == null) {
JsonNode jsonNode = getOAuthUserProfile().get(OAUTH_USER_PROFILE_ROLES_KEY);
roles = new ArrayList<String>();
if(jsonNode.isArray()) {
ArrayNode arrayNode = (ArrayNode) jsonNode;
if(arrayNode.size()>0) {
Iterator<JsonNode> iterator = arrayNode.iterator();
while(iterator.hasNext()) {
roles.add(iterator.next().asText());
}
}
}
}
return roles;
}
}

View File

@ -1,26 +1,20 @@
package org.gcube.gcat.social;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.List;
import javax.cache.Cache;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response.Status;
import org.gcube.common.gxhttp.request.GXHTTPStringRequest;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
import org.gcube.gcat.oldutils.CachesManager;
import org.gcube.gcat.persistence.ckan.CKAN;
import org.gcube.gcat.persistence.ckan.CKANUser;
import org.gcube.gcat.utils.Constants;
import org.gcube.gcat.utils.ContextUtility;
import org.gcube.gcat.utils.HTTPUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -32,55 +26,48 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class SocialService extends Thread {
public class SocialPost extends Thread {
private static final Logger logger = LoggerFactory.getLogger(SocialService.class);
private static final Logger logger = LoggerFactory.getLogger(SocialPost.class);
public static final String ITEM_URL = "Item URL";
// https://wiki.gcube-system.org/gcube/Social_Networking_Service#Write_application_post_2
protected static final String SOCIAL_SERVICE_WRITE_APPLICATION_POST_PATH = "/2/posts/write-post-app";
// https://wiki.gcube-system.org/gcube/Social_Networking_Service
protected static final String SOCIAL_SERVICE_GET_USER_INFO_PATH = "2/users/get-profile";
// String.format(NOTIFICATION_MESSAGE, fullName, title, url)
protected static final String NOTIFICATION_MESSAGE = "%s just published the item \"%s\"\n" +
"Please find it at %s\n";
protected static final String NOTIFICATION_MESSAGE = "%s just published the item \"%s\"\n"
+ "Please find it at %s\n";
protected static final String RESULT_KEY = "result";
protected static final String FULLNAME_IN_PROFILE_KEY = "fullname";
protected static final String SOCIAL_POST_TEXT_KEY = "text";
protected static final String SOCIAL_POST_ENABLE_NOTIFICATION_KEY = "enable_notification";
protected static final String SOCIAL_POST_RESPONSE_SUCCESS_KEY = "success";
protected static final String SOCIAL_POST_RESPONSE_MESSAGE_KEY = "message";
protected final GcoreEndpointReaderSNL gcoreEndpointReaderSNL;
protected final ObjectMapper objectMapper;
protected String itemID;
protected String itemURL;
protected String itemTitle;
protected List<String> tags;
protected JsonNode gCubeUserProfile;
public SocialService() throws Exception {
public SocialPost() throws Exception {
super();
this.gcoreEndpointReaderSNL = new GcoreEndpointReaderSNL();
this.objectMapper = new ObjectMapper();
}
public String getItemID() {
return itemID;
}
public void setItemID(String itemID) {
this.itemID = itemID;
}
public String getItemURL() {
return itemURL;
}
public void setItemURL(String itemURL) {
this.itemURL = itemURL;
}
@ -88,15 +75,15 @@ public class SocialService extends Thread {
public String getItemTitle() {
return itemTitle;
}
public void setItemTitle(String itemTitle) {
this.itemTitle = itemTitle;
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
@ -109,7 +96,7 @@ public class SocialService extends Thread {
String tagName = "";
if(jsonNode.has("display_name")) {
tagName = jsonNode.get("display_name").asText();
}else {
} else {
tagName = jsonNode.get("name").asText();
}
this.tags.add(tagName);
@ -117,83 +104,6 @@ public class SocialService extends Thread {
}
}
/**
* Execute the GET http request at this url, and return the result as string
* @return
* @throws Exception
*/
public JsonNode getGCubeUserProfile() throws Exception {
if(gCubeUserProfile==null) {
String username = ContextUtility.getUsername();
gCubeUserProfile = getGCubeUserProfile(username);
}
return gCubeUserProfile;
}
protected StringBuilder getStringBuilder(InputStream inputStream) throws IOException {
StringBuilder result = new StringBuilder();
try(BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while((line = reader.readLine()) != null) {
result.append(line);
}
}
return result;
}
protected String getResultAsString(HttpURLConnection httpURLConnection) throws IOException {
int responseCode = httpURLConnection.getResponseCode();
if(responseCode >= Status.BAD_REQUEST.getStatusCode()) {
Status status = Status.fromStatusCode(responseCode);
InputStream inputStream = httpURLConnection.getErrorStream();
StringBuilder result = getStringBuilder(inputStream);
logger.trace(result.toString());
throw new WebApplicationException(status);
}
InputStream inputStream = httpURLConnection.getInputStream();
String ret = getStringBuilder(inputStream).toString();
logger.trace("Got Respose is {}", ret);
return ret;
}
protected JsonNode getGCubeUserProfile(String username) throws Exception {
Cache<String,JsonNode> userCache = CachesManager.getUserCache();
if(userCache.containsKey(username))
return userCache.get(username);
else {
String socialServiceBasePath = gcoreEndpointReaderSNL.getServiceBasePath();
GXHTTPStringRequest gxhttpStringRequest = GXHTTPStringRequest.newRequest(socialServiceBasePath);
gxhttpStringRequest.header("User-Agent", Constants.CATALOGUE_NAME);
gxhttpStringRequest.header("Accept", MediaType.APPLICATION_JSON);
gxhttpStringRequest.path(SOCIAL_SERVICE_GET_USER_INFO_PATH);
HttpURLConnection httpURLConnection = gxhttpStringRequest.get();
String ret = getResultAsString(httpURLConnection);
JsonNode jsonNode = objectMapper.readTree(ret);
userCache.put(username, jsonNode);
return jsonNode;
}
}
public String getFullName() throws Exception {
try {
if(!ContextUtility.isApplication()) {
JsonNode jsonNode = getGCubeUserProfile();
JsonNode result = jsonNode.get(RESULT_KEY);
return result.get(FULLNAME_IN_PROFILE_KEY).asText();
}
}catch (Exception e) {
logger.warn("Unable to get the full name of the requesting user via Social Service. The username corresponsing to the requester token will be used.");
}
return ContextUtility.getUsername();
}
@Override
public void run() {
@ -218,9 +128,9 @@ public class SocialService extends Thread {
public void sendSocialPost(boolean notifyUsers) {
try {
String fullName = getFullName();
String fullName = CKANUser.getCurrentCKANUser().getPortalUser().getFullName();
String basePath = gcoreEndpointReaderSNL.getServiceBasePath();
String basePath = SocialServiceDiscovery.getCurrentScopeSocialServiceBasePath();
if(basePath == null) {
logger.info("Unable to write a post because there is no social networking service available");
return;
@ -242,7 +152,7 @@ public class SocialService extends Thread {
}
String message = messageWriter.toString();
logger.debug("The post that is going to be written is\n{}",message);
logger.debug("The post that is going to be written is\n{}", message);
ObjectNode objectNode = objectMapper.createObjectNode();
objectNode.put(SOCIAL_POST_TEXT_KEY, message);
@ -251,16 +161,14 @@ public class SocialService extends Thread {
// Do not use ApplicationMode class here because is a thread and change the current token could impact
// on the other threads.
GXHTTPStringRequest gxhttpStringRequest = GXHTTPStringRequest.newRequest(basePath);
GXHTTPStringRequest gxhttpStringRequest = GXHTTPStringRequest.newRequest(basePath);
gxhttpStringRequest.from(Constants.CATALOGUE_NAME);
gxhttpStringRequest.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
gxhttpStringRequest.setSecurityToken(Constants.getCatalogueApplicationToken());
gxhttpStringRequest.path(SOCIAL_SERVICE_WRITE_APPLICATION_POST_PATH);
HttpURLConnection httpURLConnection = gxhttpStringRequest.post(objectMapper.writeValueAsString(objectNode));
String ret = getResultAsString(httpURLConnection);
String ret = HTTPUtility.getResultAsString(httpURLConnection);
JsonNode jsonNode = objectMapper.readTree(ret);
if(jsonNode.get(SOCIAL_POST_RESPONSE_SUCCESS_KEY).asBoolean()) {
logger.info("Post written : {}", message);

View File

@ -3,7 +3,9 @@ package org.gcube.gcat.social;
import static org.gcube.resources.discovery.icclient.ICFactory.client;
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.gcube.common.resources.gcore.GCoreEndpoint;
import org.gcube.gcat.utils.ContextUtility;
@ -19,21 +21,53 @@ import org.slf4j.LoggerFactory;
*/
// TODO Add a context based cache
public class GcoreEndpointReaderSNL {
public class SocialServiceDiscovery {
private static final String RESOURCE = "jersey-servlet";
private static final String SERVICE_NAME = "SocialNetworking";
private static final String SERVICE_CLASSE = "Portal";
private static Logger logger = LoggerFactory.getLogger(GcoreEndpointReaderSNL.class);
private static final String SOCIAL_SERVICE_HA_PROXY_URL = "https://api.d4science.org/rest";
private static Logger logger = LoggerFactory.getLogger(SocialServiceDiscovery.class);
private String serviceBasePath;
// Map<String contextName, String basePath>
private static Map<String, String> socialServiceBasePathPerContext;
static {
socialServiceBasePathPerContext = new HashMap<>();
}
public static String getCurrentScopeSocialServiceBasePath() throws Exception {
String contex = ContextUtility.getCurrentContext();
String serviceBasePath = socialServiceBasePathPerContext.get(contex);
if(serviceBasePath==null) {
SocialServiceDiscovery gcoreEndpointReaderSNL = new SocialServiceDiscovery();
serviceBasePath = gcoreEndpointReaderSNL.getServiceBasePath();
socialServiceBasePathPerContext.put(contex, serviceBasePath);
}
return serviceBasePath;
}
/**
* Discover the gcore endpoint for the social networking service.
* @throws Exception the exception
*/
public GcoreEndpointReaderSNL() throws Exception {
private SocialServiceDiscovery() throws Exception {
getServiceBasePathViaServiceEndpoint();
if(serviceBasePath==null) {
getServiceBasePathViaGCoreEndpoint();
}
}
protected void getServiceBasePathViaServiceEndpoint() throws Exception {
// TODO Discover on IS
serviceBasePath = SOCIAL_SERVICE_HA_PROXY_URL;
}
protected void getServiceBasePathViaGCoreEndpoint() throws Exception {
try {
SimpleQuery query = queryFor(GCoreEndpoint.class);
query.addCondition(String.format("$resource/Profile/ServiceClass/text() eq '%s'", SERVICE_CLASSE));
@ -66,6 +100,7 @@ public class GcoreEndpointReaderSNL {
}
}
/**
* @return the base path of the service
*/

View File

@ -0,0 +1,62 @@
package org.gcube.gcat.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response.Status;
import org.gcube.common.gxhttp.request.GXHTTPStringRequest;
import org.gcube.gcat.persistence.ckan.CKAN;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HTTPUtility {
private static final Logger logger = LoggerFactory.getLogger(CKAN.class);
public static StringBuilder getStringBuilder(InputStream inputStream) throws IOException {
StringBuilder result = new StringBuilder();
try(BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while((line = reader.readLine()) != null) {
result.append(line);
}
}
return result;
}
public static GXHTTPStringRequest createGXHTTPStringRequest(String url, String path, boolean post) throws UnsupportedEncodingException {
GXHTTPStringRequest gxhttpStringRequest = GXHTTPStringRequest.newRequest(url);
gxhttpStringRequest.from(Constants.CATALOGUE_NAME);
if(post) {
gxhttpStringRequest.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
}
gxhttpStringRequest.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
gxhttpStringRequest.path(path);
return gxhttpStringRequest;
}
public static String getResultAsString(HttpURLConnection httpURLConnection) throws IOException {
int responseCode = httpURLConnection.getResponseCode();
if(responseCode >= Status.BAD_REQUEST.getStatusCode()) {
Status status = Status.fromStatusCode(responseCode);
InputStream inputStream = httpURLConnection.getErrorStream();
StringBuilder result = getStringBuilder(inputStream);
logger.trace(result.toString());
throw new WebApplicationException(status);
}
InputStream inputStream = httpURLConnection.getInputStream();
String ret = getStringBuilder(inputStream).toString();
logger.trace("Got Respose is {}", ret);
return ret;
}
}

View File

@ -25,11 +25,6 @@ public class URIResolver {
private static final String ENTITY_TYPE = "entity_context";
private static final String ENTITY_NAME = "entity_name";
@Deprecated
private static final String PRODUCT = "product";
@Deprecated
private static final String CATALOGUE_PLAIN_URL = "clear_url";
protected ObjectMapper mapper;
public URIResolver() {
@ -58,11 +53,6 @@ public class URIResolver {
requestContent.put(ENTITY_TYPE, EntityContext.DATASET.toString());
requestContent.put(ENTITY_NAME, name);
/* Uncomment the following two rows to build a version compliant with old URI RESOLVER
requestContent.put(ENTITY_TYPE, PRODUCT);
requestContent.put(CATALOGUE_PLAIN_URL, String.valueOf(true));
*/
GXHTTPStringRequest gxhttpStringRequest = GXHTTPStringRequest.newRequest(uriResolverURL);
gxhttpStringRequest.from(Constants.CATALOGUE_NAME);
gxhttpStringRequest.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);

View File

@ -1,8 +1,6 @@
package org.gcube.gcat.persistence.ckan;
import org.gcube.gcat.ContextTest;
import org.gcube.gcat.persistence.ckan.CKANOrganization;
import org.gcube.gcat.persistence.ckan.CKANUtility;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -11,6 +9,7 @@ public class CKANOrganizationTest extends ContextTest {
private static Logger logger = LoggerFactory.getLogger(CKANOrganizationTest.class);
/*
@Test
public void getUserRole() throws Exception {
CKANOrganization ckanOrganization = new CKANOrganization();
@ -19,6 +18,7 @@ public class CKANOrganizationTest extends ContextTest {
String ret = ckanOrganization.getUserRole("luca.frosini");
logger.debug("{}", ret);
}
*/
@Test
public void listOrganization() throws Exception {

View File

@ -66,4 +66,10 @@ public class CKANUserTest extends ContextTest {
}
@Test
public void testAddSpecialUserToOrganization() throws Exception {
CKANUser ckanUser = getCKANUser();
ckanUser.addUserToOrganization();
}
}

View File

@ -13,25 +13,12 @@ public class CKANUtilityTest extends ContextTest {
private static Logger logger = LoggerFactory.getLogger(CKANPackageTest.class);
private static final String USERNAME = "luca_frosini";
@Test
public void testGetApiKey() throws Exception {
String ckanAPI = CKANUtility.getApiKey(USERNAME);
logger.debug("User {} has the following API key {}", USERNAME, ckanAPI);
String ckanAPI = CKANUtility.getApiKey();
logger.debug("User {} has the following API key {}", CKANUser.getCKANUsername(), ckanAPI);
}
@Test
public void testAddUserToOrganization() throws Exception {
CKANUtility.addUserToOrganization(USERNAME, CKANUtility.MEMBER_ROLE, true);
}
@Test
public void testAddSpecialUserToOrganization() throws Exception {
CKANUtility.addUserToOrganization("luca_frosini", "editor", true);
}
}

View File

@ -0,0 +1,21 @@
package org.gcube.gcat.social;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class PortalUserTest {
private static final Logger logger = LoggerFactory.getLogger(PortalUserTest.class);
@Test
public void testGetUserProfile() throws Exception {
PortalUser portalUser = new PortalUser();
JsonNode jsonNode = portalUser.getOAuthUserProfile();
ObjectMapper objectMapper = new ObjectMapper();
logger.debug("OAuth User Profile is {}", objectMapper.writeValueAsString(jsonNode));
}
}

View File

@ -10,29 +10,19 @@ import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class SocialServiceTest extends ContextTest {
public class SocialPostTest extends ContextTest {
private static final Logger logger = LoggerFactory.getLogger(SocialServiceTest.class);
@Test
public void testGetUserProfile() throws Exception {
SocialService socialService = new SocialService();
JsonNode jsonNode = socialService.getGCubeUserProfile();
ObjectMapper objectMapper = new ObjectMapper();
logger.debug("gCube User Profile is {}", objectMapper.writeValueAsString(jsonNode));
}
private static final Logger logger = LoggerFactory.getLogger(SocialPostTest.class);
@Test
public void testToken() throws Exception {
logger.debug("Application Token is {}", Constants.getCatalogueApplicationToken());
ContextTest.setContext(Constants.getCatalogueApplicationToken());
}
@Test
public void testSendPost() throws Exception {
SocialService socialService = new SocialService();
SocialPost socialService = new SocialPost();
socialService.setItemID(UUID.randomUUID().toString());
socialService.setItemTitle("Test Item");
socialService.setItemURL("http://www.d4science.org");