Merged from private branch

git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-catalogue/catalogue-ws@166966 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Luca Frosini 2018-04-12 15:56:38 +00:00
parent 0a49656129
commit a881355db7
27 changed files with 1825 additions and 1856 deletions

View File

@ -6,6 +6,7 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src/test/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>

26
pom.xml
View File

@ -11,7 +11,7 @@
<groupId>org.gcube.data-catalogue</groupId>
<artifactId>catalogue-ws</artifactId>
<packaging>war</packaging>
<version>1.2.0-SNAPSHOT</version>
<version>1.3.0-SNAPSHOT</version>
<name>catalogue-ws</name>
<description>
@ -22,7 +22,14 @@
<dependencies>
<dependency>
<groupId>org.gcube.distribution</groupId>
<artifactId>maven-smartgears-bom</artifactId>
<artifactId>gcube-bom</artifactId>
<version>LATEST</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.gcube.distribution</groupId>
<artifactId>gcube-smartgears-bom</artifactId>
<version>LATEST</version>
<type>pom</type>
<scope>import</scope>
@ -40,11 +47,19 @@
</properties>
<dependencies>
<!-- ehCAChe -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.0</version>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.5.2</version>
<scope>runtime</scope>
</dependency>
<!-- END ehCAChe -->
<dependency>
<groupId>org.gcube.resources.discovery</groupId>
<artifactId>ic-client</artifactId>
@ -103,6 +118,7 @@
<artifactId>jersey-media-multipart</artifactId>
<version>${version.jersey}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-sse</artifactId>

View File

@ -6,23 +6,45 @@ import org.json.simple.JSONObject;
* A custom field bean. It also stores index of the category and of the metadata field associated.
* These are used to sort them before pushing the content to CKAN.
* If they are missing, indexes are set to Integer.MAX_VALUE.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
public class CustomField implements Comparable<CustomField> {
private String key;
private String qualifiedKey;
private String value;
private int indexMetadataField = Integer.MAX_VALUE;
private int indexCategory = Integer.MAX_VALUE;
private int indexMetadataField = Integer.MAX_VALUE;
private void init(String key, String value, int indexCategory, int indexMetadataField) {
if(key == null || value == null || key.isEmpty()) {
throw new IllegalArgumentException(
"A custom field must have a key and a value! Provided values are " + key + "=" + value);
}
this.key = key;
this.qualifiedKey = key;
this.value = value;
this.indexMetadataField = indexMetadataField;
this.indexCategory = indexCategory;
if(this.indexCategory < 0) {
this.indexCategory = Integer.MAX_VALUE;
}
if(this.indexMetadataField < 0) {
this.indexMetadataField = Integer.MAX_VALUE;
}
}
public CustomField(JSONObject object) {
super();
this.key = (String)object.get("key");
this.qualifiedKey = key;
this.value = (String)object.get("value");
if(key == null || value == null || key.isEmpty())
throw new IllegalArgumentException("A custom field must have a key and a value! Provided object is " + object.toString());
init((String) object.get("key"), (String) object.get("value"), -1, -1);
}
/**
@ -31,9 +53,7 @@ public class CustomField implements Comparable<CustomField>{
*/
public CustomField(String key, String value) {
super();
this.key = key;
this.qualifiedKey = key;
this.value = value;
init(key, value, -1, -1);
}
/**
@ -44,45 +64,7 @@ public class CustomField implements Comparable<CustomField>{
*/
public CustomField(String key, String value, int indexCategory, int indexMetadataField) {
super();
this.key = key;
this.value = value;
this.indexMetadataField = indexMetadataField;
this.indexCategory = indexCategory;
this.qualifiedKey = key;
if(this.indexCategory < 0)
this.indexCategory = Integer.MAX_VALUE;
if(this.indexMetadataField < 0)
this.indexMetadataField = Integer.MAX_VALUE;
}
public int getIndexMetadataField() {
return indexMetadataField;
}
public String getQualifiedKey() {
return qualifiedKey;
}
public void setQualifiedKey(String qualifiedKey) {
this.qualifiedKey = qualifiedKey;
}
public void setIndexMetadataField(int indexMetadataField) {
this.indexMetadataField = indexMetadataField;
if(this.indexMetadataField < 0)
this.indexMetadataField = Integer.MAX_VALUE;
}
public int getIndexCategory() {
return indexCategory;
}
public void setIndexCategory(int indexCategory) {
this.indexCategory = indexCategory;
if(this.indexCategory < 0)
this.indexCategory = Integer.MAX_VALUE;
init(key, value, indexCategory, indexMetadataField);
}
public String getKey() {
@ -101,22 +83,52 @@ public class CustomField implements Comparable<CustomField>{
this.value = value;
}
public String getQualifiedKey() {
return qualifiedKey;
}
public void setQualifiedKey(String qualifiedKey) {
this.qualifiedKey = qualifiedKey;
}
public int getIndexCategory() {
return indexCategory;
}
public void setIndexCategory(int indexCategory) {
this.indexCategory = indexCategory;
if(this.indexCategory < 0)
this.indexCategory = Integer.MAX_VALUE;
}
public int getIndexMetadataField() {
return indexMetadataField;
}
public void setIndexMetadataField(int indexMetadataField) {
this.indexMetadataField = indexMetadataField;
if(this.indexMetadataField < 0) {
this.indexMetadataField = Integer.MAX_VALUE;
}
}
@Override
public String toString() {
return "CustomField [key=" + key + ", qualifiedKey=" + qualifiedKey
+ ", value=" + value + ", indexMetadataField="
+ indexMetadataField + ", indexCategory=" + indexCategory + "]";
return "CustomField [key=" + key + ", qualifiedKey=" + qualifiedKey + ", value=" + value
+ ", indexMetadataField=" + indexMetadataField + ", indexCategory=" + indexCategory + "]";
}
@Override
public int compareTo(CustomField o) {
if(this.indexCategory == o.indexCategory) {
if(this.indexMetadataField == o.indexMetadataField)
if(this.indexMetadataField == o.indexMetadataField) {
return 0;
else
} else {
return this.indexMetadataField > o.indexMetadataField ? 1 : -1;
}
else
} else {
return this.indexCategory > o.indexCategory ? 1 : -1;
}
}
}

View File

@ -0,0 +1,73 @@
package org.gcube.datacatalogue.catalogue.entities;
import javax.ws.rs.core.MultivaluedMap;
import org.gcube.datacatalogue.catalogue.utils.CatalogueUtils;
import org.gcube.datacatalogue.catalogue.utils.Constants;
import org.gcube.datacatalogue.catalogue.utils.ContextUtils;
import org.gcube.datacatalogue.catalogue.utils.Delegator;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.server.utils.CatalogueUtilMethods;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.trentorise.opendata.jackan.model.CkanDataset;
public class CatalogueItem {
private static final Logger logger = LoggerFactory.getLogger(CatalogueItem.class);
protected String id;
protected JSONObject item;
public CatalogueItem() {}
public CatalogueItem(String jsonString) throws ParseException {
JSONParser parser = new JSONParser();
this.item = (JSONObject) parser.parse(jsonString);
}
private void applicationChecks(String authorizationErroMessage) throws Exception {
if(ContextUtils.isApplication()) {
logger.debug("Application Token Request");
DataCatalogue dataCatalogue = CatalogueUtils.getCatalogue();
CkanDataset dataset = dataCatalogue.getDataset(id, CatalogueUtils.fetchSysAPI());
String organization = CatalogueUtilMethods.getCKANOrganization();
if(organization.equalsIgnoreCase(dataset.getOrganization().getName())
&& ContextUtils.getUsername().equals(dataset.getAuthor())) {
return;
}
throw new Exception(authorizationErroMessage);
}
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String create() {
return null;
}
public String read() {
return Delegator.delegateGet(Constants.ITEM_SHOW, (MultivaluedMap<String,String>) null);
}
public String update() {
return null;
}
public String delete() {
return null;
}
}

View File

@ -1,33 +1,66 @@
package org.gcube.datacatalogue.catalogue.utils;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
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 org.json.simple.JSONObject;
/**
* Handle caches via Ehcache stuff.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
public class CachesManager {
private static CacheManager cacheManager;
public static final CachesManager singleton = new 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 CachesManager(){
cacheManager = CacheManager.newInstance();
private static final CacheManager cacheManager;
private static final Cache<String, DataCalogueMetadataFormatReader> readerCache;
private static final Cache<String, JSONObject> 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, JSONObject> userConfiguration =
new MutableConfiguration<String, JSONObject>()
.setTypes(String.class, JSONObject.class)
.setStoreByValue(false)
.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ONE_MINUTE));
userCache = cacheManager.createCache(PROFILES_USERS_CACHE, userConfiguration);
}
public static Cache getCache(String name){
return cacheManager.getCache(name);
private CachesManager() {}
public static Cache<String, DataCalogueMetadataFormatReader> getReaderCache() {
return readerCache;
}
public static Cache<String, JSONObject> getUserCache() {
return userCache;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
cacheManager.shutdown();
cacheManager.close();
}
}

View File

@ -4,17 +4,18 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import javax.cache.Cache;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.gcube.common.authorization.library.ClientType;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.ClientInfo;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueFactory;
@ -26,6 +27,7 @@ import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataFormat;
import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.NamespaceCategory;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.trentorise.opendata.jackan.model.CkanGroup;
@ -33,12 +35,13 @@ import eu.trentorise.opendata.jackan.model.CkanOrganization;
/**
* Utils methods.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
@SuppressWarnings("unchecked")
public class CatalogueUtils {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CatalogueUtils.class);
private static final Logger logger = LoggerFactory.getLogger(CatalogueUtils.class);
/**
* Retrieve an instance of the library for the current scope
@ -46,22 +49,11 @@ public class CatalogueUtils {
* @throws Exception
*/
public static DataCatalogue getCatalogue() throws Exception {
String context = ScopeProvider.instance.get();
logger.debug("Discovering ckan instance into scope " + context);
logger.debug("Discovering ckan instance in context {}", context);
return DataCatalogueFactory.getFactory().getUtilsPerScope(context);
}
/**
* Retrieve an instance of the library for the scope
* @param scope if it is null it is evaluated from the session
* @return
* @throws Exception
*/
public static CkanGroup createGroupAsSysAdmin(String title, String groupName, String description) throws Exception{
return getCatalogue().createGroup(groupName, title, description);
}
/**
* Get the group hierarchy
* @param groupName
@ -69,19 +61,29 @@ public class CatalogueUtils {
* @return
* @throws Exception
*/
public static List<String> getGroupHierarchyNames(String groupName, String username, boolean isApplication) throws Exception{
public static List<String> getGroupHierarchyNames(String groupName) throws Exception {
List<String> toReturn = new ArrayList<String>();
String apiKey = isApplication ? fetchSysAPI(ScopeProvider.instance.get()): getCatalogue().getApiKeyFromUsername(username);
String apiKey = CatalogueUtils.getApiKey();
List<CkanGroup> ckanGroups = getCatalogue().getParentGroups(groupName, apiKey);
if(ckanGroups != null && !ckanGroups.isEmpty()) {
for(CkanGroup ckanGroup : ckanGroups) {
toReturn.add(ckanGroup.getName());
}
}
return toReturn;
}
private static DataCalogueMetadataFormatReader getDataCalogueMetadataFormatReader() throws Exception {
Cache<String, DataCalogueMetadataFormatReader> readerCache = CachesManager.getReaderCache();
String context = ScopeProvider.instance.get();
DataCalogueMetadataFormatReader reader;
if(readerCache.containsKey(context))
reader = (DataCalogueMetadataFormatReader) readerCache.get(context);
else {
reader = new DataCalogueMetadataFormatReader();
readerCache.put(context, reader);
}
return reader;
}
/**
@ -92,18 +94,9 @@ public class CatalogueUtils {
*/
public static List<String> getProfilesNames() throws Exception {
Cache profilesCache = CachesManager.getCache(CachesManager.PROFILES_READERS_CACHE);
String context = ScopeProvider.instance.get();
DataCalogueMetadataFormatReader reader = getDataCalogueMetadataFormatReader();
List<String> toReturn = new ArrayList<String>();
DataCalogueMetadataFormatReader reader;
if(profilesCache.isKeyInCache(context))
reader = (DataCalogueMetadataFormatReader) profilesCache.get(context).getObjectValue();
else{
reader = new DataCalogueMetadataFormatReader();
profilesCache.put(new Element(context, reader));
}
List<MetadataProfile> listProfiles = reader.getListOfMetadataProfiles();
if(listProfiles != null && !listProfiles.isEmpty()) {
@ -123,16 +116,7 @@ public class CatalogueUtils {
*/
public static String getProfileSource(String profileName) throws Exception {
Cache profilesCache = CachesManager.getCache(CachesManager.PROFILES_READERS_CACHE);
String context = ScopeProvider.instance.get();
DataCalogueMetadataFormatReader reader;
if(profilesCache.isKeyInCache(context))
reader = (DataCalogueMetadataFormatReader) profilesCache.get(context).getObjectValue();
else{
reader = new DataCalogueMetadataFormatReader();
profilesCache.put(new Element(context, reader));
}
DataCalogueMetadataFormatReader reader = getDataCalogueMetadataFormatReader();
List<MetadataProfile> listProfiles = reader.getListOfMetadataProfiles();
String xmlToReturn = null;
@ -156,18 +140,7 @@ public class CatalogueUtils {
* @throws Exception
*/
public static List<NamespaceCategory> getNamespaceCategories() throws Exception {
Cache profilesCache = CachesManager.getCache(CachesManager.PROFILES_READERS_CACHE);
String context = ScopeProvider.instance.get();
DataCalogueMetadataFormatReader reader;
if(profilesCache.isKeyInCache(context))
reader = (DataCalogueMetadataFormatReader) profilesCache.get(context).getObjectValue();
else{
reader = new DataCalogueMetadataFormatReader();
profilesCache.put(new Element(context, reader));
}
DataCalogueMetadataFormatReader reader = getDataCalogueMetadataFormatReader();
return reader.getListOfNamespaceCategories();
}
@ -180,17 +153,7 @@ public class CatalogueUtils {
*/
public static MetadataFormat getMetadataProfile(String profileName) throws Exception {
Cache profilesCache = CachesManager.getCache(CachesManager.PROFILES_READERS_CACHE);
String context = ScopeProvider.instance.get();
DataCalogueMetadataFormatReader reader;
if(profilesCache.isKeyInCache(context))
reader = (DataCalogueMetadataFormatReader) profilesCache.get(context).getObjectValue();
else{
reader = new DataCalogueMetadataFormatReader();
profilesCache.put(new Element(context, reader));
}
DataCalogueMetadataFormatReader reader = getDataCalogueMetadataFormatReader();
List<MetadataProfile> listProfiles = reader.getListOfMetadataProfiles();
if(listProfiles != null && !listProfiles.isEmpty()) {
@ -218,14 +181,13 @@ public class CatalogueUtils {
* @return
*/
public static JSONObject createJSONObjectMin(boolean success, String errorMessage) {
JSONObject obj = new JSONObject();
obj.put(Constants.HELP_KEY, Constants.HELP_URL_GCUBE_CATALOGUE);
obj.put(Constants.SUCCESS_KEY, success);
if(errorMessage != null)
if(errorMessage != null) {
obj.put(Constants.MESSAGE_ERROR_KEY, errorMessage);
}
return obj;
}
/**
@ -234,34 +196,40 @@ public class CatalogueUtils {
* @param organization
* @throws Exception
*/
public static void checkRole(String username, String organization) throws Exception {
DataCatalogue catalogue = getCatalogue();
public static void checkRole(String organization) throws Exception {
DataCatalogue dataCatalogue = getCatalogue();
// check organization exists
CkanOrganization org = catalogue.getOrganizationByName(organization);
CkanOrganization org = dataCatalogue.getOrganizationByName(organization);
if(org == null)
if(org == null) {
throw new Exception("It seems that an organization with name " + organization + " doesn't exist!");
Map<String, Map<CkanOrganization, RolesCkanGroupOrOrg>> rolesPerOrganization = catalogue.getUserRoleByOrganization(username, catalogue.getApiKeyFromUsername(username));
if(rolesPerOrganization.get(org.getName()).values().contains(RolesCkanGroupOrOrg.MEMBER))
throw new Exception("It seems you are neither Catalogue-Admin nor Catalogue-Editor in organization " + organization + "!");
}
Map<String,Map<CkanOrganization,RolesCkanGroupOrOrg>> rolesPerOrganization = dataCatalogue
.getUserRoleByOrganization(ContextUtils.getUsername(),
dataCatalogue.getApiKeyFromUsername(ContextUtils.getUsername()));
if(rolesPerOrganization.get(org.getName()).values().contains(RolesCkanGroupOrOrg.MEMBER)) {
throw new Exception("It seems you are neither Catalogue-Admin nor Catalogue-Editor in organization "
+ organization + "!");
}
}
/**
* Execute the GET http request at this url, and return the result as string
* @return
* @throws Exception
*/
public static JSONObject getUserProfile(String userId) throws Exception{
public static JSONObject getUserProfile() throws Exception {
Cache profilesCache = CachesManager.getCache(CachesManager.PROFILES_USERS_CACHE);
ClientInfo clientInfo = AuthorizationProvider.instance.get().getClient();
String username = clientInfo.getId();
if(profilesCache.isKeyInCache(userId))
return (JSONObject) profilesCache.get(userId).getObjectValue();
Cache<String,JSONObject> userCache = CachesManager.getUserCache();
if(userCache.containsKey(username))
return userCache.get(username);
else {
GcoreEndpointReaderSNL socialService = new GcoreEndpointReaderSNL();
String socialServiceUrl = socialService.getServiceBasePath();
@ -271,7 +239,7 @@ public class CatalogueUtils {
HttpResponse response = client.execute(getRequest);
JSONParser parser = new JSONParser();
JSONObject profile = (JSONObject) parser.parse(EntityUtils.toString(response.getEntity()));
profilesCache.put(new Element(userId, profile));
userCache.put(username, profile);
return profile;
} catch(Exception e) {
logger.error("error while performing get method " + e.toString());
@ -285,22 +253,36 @@ public class CatalogueUtils {
* @return
* @throws Exception
*/
public static String fetchSysAPI(String context) throws Exception{
DataCatalogueRunningCluster catalogueRunningInstance = new DataCatalogueRunningCluster(context);
public static String fetchSysAPI() throws Exception {
DataCatalogueRunningCluster catalogueRunningInstance = new DataCatalogueRunningCluster(
ContextUtils.getContext());
return catalogueRunningInstance.getSysAdminToken();
}
/**
* Check if the token belongs to an application token
* @param caller
* @return
*/
public static boolean isApplicationToken(Caller caller){
public static String getApiKey() throws Exception {
return ContextUtils.isApplication() ? fetchSysAPI()
: getCatalogue().getApiKeyFromUsername(ContextUtils.getUsername());
}
return caller.getClient().getType().equals(ClientType.EXTERNALSERVICE);
public static String getIdFromUriInfo(String idName, UriInfo uriInfo) throws Exception {
MultivaluedMap<String,String> queryParams = uriInfo.getQueryParameters(false);
List<String> ids = queryParams.get(idName);
if(ids == null || ids.isEmpty()) {
throw new Exception("'" + idName + "' field is missing!");
}else if(ids.size()>1) {
throw new Exception("More than one '\" + idName + \"' has been provided!");
}
return ids.get(0);
}
public static String getIdFromJSONString(String idName, String jsonString) throws Exception {
JSONParser parser = new JSONParser();
JSONObject jsonObject = (JSONObject) parser.parse(jsonString);
String id = (String) jsonObject.get(idName);
if(id == null || id.isEmpty()) {
throw new Exception("'" + idName + "' field is missing!");
}
return id;
}
}

View File

@ -2,7 +2,8 @@ package org.gcube.datacatalogue.catalogue.utils;
/**
* Constants used within this service.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
public class Constants {

View File

@ -0,0 +1,39 @@
package org.gcube.datacatalogue.catalogue.utils;
import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
import org.gcube.common.authorization.library.ClientType;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.scope.api.ScopeProvider;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class ContextUtils {
private ContextUtils(){}
public static String getContext() throws ObjectNotFound, Exception {
String context = ScopeProvider.instance.get();
if (context == null) {
String token = SecurityTokenProvider.instance.get();
try {
return org.gcube.common.authorization.client.Constants.authorizationService().get(token).getContext();
}catch (Exception e) {
new RuntimeException(e);
}
}
return context;
}
public static String getUsername() {
return AuthorizationProvider.instance.get().getClient().getId();
}
public static boolean isApplication() {
return AuthorizationProvider.instance.get().getClient().getType().equals(ClientType.EXTERNALSERVICE);
}
}

View File

@ -22,8 +22,6 @@ import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
@ -32,57 +30,60 @@ import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.slf4j.LoggerFactory;
/**
* As the name says, it just delegates GET/POST operations to CKAN
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
@SuppressWarnings("unchecked")
public class Delegator {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Delegator.class);
public static String delegateGet(String method, UriInfo uriInfo) {
return delegateGet(method, uriInfo.getQueryParameters(false));
}
/**
* Execute the get
* @param caller
* @param context
* @param method
* @param uriInfo
* @return
* @throws Exception
*/
public static String delegateGet(Caller caller, String context, String method, UriInfo uriInfo, boolean isAppRequest){
String username = caller.getClient().getId();
public static String delegateGet(String method, MultivaluedMap<String,String> undecodedParams) {
try(CloseableHttpClient client = HttpClientBuilder.create().build();) {
DataCatalogue catalogue = CatalogueUtils.getCatalogue();
String authorization = isAppRequest ? CatalogueUtils.fetchSysAPI(ScopeProvider.instance.get()) : catalogue.getApiKeyFromUsername(username);
String requestPath = catalogue.getCatalogueUrl().endsWith("/") ? catalogue.getCatalogueUrl() : catalogue.getCatalogueUrl() + "/";
requestPath += method;
MultivaluedMap<String, String> undecodedParams = uriInfo.getQueryParameters(false);
Iterator<Entry<String, List<String>>> iterator = undecodedParams.entrySet().iterator();
String authorization = CatalogueUtils.getApiKey();
String requestPath = catalogue.getCatalogueUrl().endsWith("/") ? catalogue.getCatalogueUrl()
: catalogue.getCatalogueUrl() + "/";
requestPath += method;
if(undecodedParams !=null) {
Iterator<Entry<String,List<String>>> iterator = undecodedParams.entrySet().iterator();
while(iterator.hasNext()) {
Map.Entry<java.lang.String,java.util.List<java.lang.String>> entry = (Map.Entry<java.lang.String,java.util.List<java.lang.String>>) iterator
.next();
if(entry.getKey().equals(Constants.GCUBE_TOKEN_PARAMETER))
if(entry.getKey().equals(Constants.GCUBE_TOKEN_PARAMETER)) {
continue;
else{
} else {
List<String> values = entry.getValue();
for(String value : values) {
requestPath += entry.getKey() + "=" + value + "&";
}
}
}
}
if(requestPath.endsWith("&"))
if(requestPath.endsWith("&")) {
requestPath = requestPath.substring(0, requestPath.length() - 1);
}
HttpGet request = new HttpGet(requestPath);
if(authorization != null)
if(authorization != null) {
request.addHeader(Constants.AUTH_CKAN_HEADER, authorization);
}
logger.debug("******* REQUEST URL IS " + requestPath);
@ -100,7 +101,6 @@ public class Delegator {
return CatalogueUtils.createJSONOnFailure("Failed to serve the request: " + e);
}
}
/**
@ -112,25 +112,22 @@ public class Delegator {
* @param uriInfo
* @throws Exception
*/
public static String delegatePost(Caller caller, String context,
String method, String json, UriInfo uriInfo, boolean isAppRequest){
String username = caller.getClient().getId();
public static String delegatePost(String method, String json, UriInfo uriInfo) {
try(CloseableHttpClient client = HttpClientBuilder.create().build();) {
DataCatalogue catalogue = CatalogueUtils.getCatalogue();
DataCatalogue dataCatalogue = CatalogueUtils.getCatalogue();
String authorization = isAppRequest ? CatalogueUtils.fetchSysAPI(ScopeProvider.instance.get()) : catalogue.getApiKeyFromUsername(username);
String requestPath = catalogue.getCatalogueUrl().endsWith("/") ? catalogue.getCatalogueUrl() : catalogue.getCatalogueUrl() + "/";
String authorization = CatalogueUtils.getApiKey();
String requestPath = dataCatalogue.getCatalogueUrl().endsWith("/") ? dataCatalogue.getCatalogueUrl()
: dataCatalogue.getCatalogueUrl() + "/";
requestPath += method + "?";
MultivaluedMap<String,String> undecodedParams = uriInfo.getQueryParameters(false);
Iterator<Entry<String,List<String>>> iterator = undecodedParams.entrySet().iterator();
while(iterator.hasNext()) {
Map.Entry<java.lang.String, java.util.List<java.lang.String>> entry = (Map.Entry<java.lang.String, java.util.List<java.lang.String>>) iterator
.next();
Map.Entry<java.lang.String,java.util.List<java.lang.String>> entry =
(Map.Entry<java.lang.String,java.util.List<java.lang.String>>) iterator.next();
if(entry.getKey().equals(Constants.GCUBE_TOKEN_PARAMETER))
continue;
@ -143,8 +140,9 @@ public class Delegator {
}
}
if(requestPath.endsWith("&"))
if(requestPath.endsWith("&")) {
requestPath = requestPath.substring(0, requestPath.length() - 1);
}
logger.debug("POST request url is going to be " + requestPath);
@ -171,40 +169,33 @@ public class Delegator {
return CatalogueUtils.createJSONOnFailure("Failed to serve the request: " + e);
}
}
/**
* Execute post with multipart (e.g. for resource upload)
* @param caller
* @param context
* @param resourceCreate
* @param method
* @param multiPart
* @param uriInfo
* @return
*/
public static String delegatePost(Caller caller, String context,
String method, FormDataMultiPart multiPart, UriInfo uriInfo, boolean isAppRequest) {
String username = caller.getClient().getId();
public static String delegatePost(String method, FormDataMultiPart multiPart, UriInfo uriInfo) {
try {
DataCatalogue catalogue = CatalogueUtils.getCatalogue();
String authorization = isAppRequest ? CatalogueUtils.fetchSysAPI(ScopeProvider.instance.get()) : catalogue.getApiKeyFromUsername(username);
String requestPath = catalogue.getCatalogueUrl().endsWith("/") ? catalogue.getCatalogueUrl() : catalogue.getCatalogueUrl() + "/";
String authorization = CatalogueUtils.getApiKey();
String requestPath = catalogue.getCatalogueUrl().endsWith("/") ? catalogue.getCatalogueUrl()
: catalogue.getCatalogueUrl() + "/";
requestPath += method + "?";
MultivaluedMap<String,String> undecodedParams = uriInfo.getQueryParameters(false);
Iterator<Entry<String,List<String>>> iterator = undecodedParams.entrySet().iterator();
while(iterator.hasNext()) {
Map.Entry<java.lang.String, java.util.List<java.lang.String>> entry = (Map.Entry<java.lang.String, java.util.List<java.lang.String>>) iterator
.next();
Map.Entry<java.lang.String,java.util.List<java.lang.String>> entry =
(Map.Entry<java.lang.String,java.util.List<java.lang.String>>) iterator.next();
if(entry.getKey().equals("Constants.AUTH_CKAN_HEADER"))
if(entry.getKey().equals(Constants.AUTH_CKAN_HEADER)) {
continue;
else{
}else {
List<String> values = entry.getValue();
for(String value : values) {
requestPath += entry.getKey() + "=" + value + "&";
@ -212,8 +203,9 @@ public class Delegator {
}
}
if(requestPath.endsWith("&"))
if(requestPath.endsWith("&")) {
requestPath = requestPath.substring(0, requestPath.length() - 1);
}
logger.debug("POST request url is going to be " + requestPath);
@ -230,15 +222,14 @@ public class Delegator {
if(fileLenghtMegaByte > Constants.MAX_UPLOADABLE_FILE_SIZE_MB)
throw new Exception("Exceeding maximum uploadable file size!");
}else
} else {
throw new Exception("No 'upload' field has been provided!");
}
Client client = ClientBuilder.newClient();
client.register(MultiPartFeature.class);
WebTarget webResource = client.target(requestPath);
JSONObject jsonRes =
webResource
.request(MediaType.APPLICATION_JSON)
JSONObject jsonRes = webResource.request(MediaType.APPLICATION_JSON)
.header(Constants.AUTH_CKAN_HEADER, authorization)
.post(Entity.entity(multiPart, multiPart.getMediaType()), JSONObject.class);
@ -254,6 +245,4 @@ public class Delegator {
}
}
}

View File

@ -1,6 +1,3 @@
/**
*
*/
package org.gcube.datacatalogue.catalogue.utils;
import static org.gcube.resources.discovery.icclient.ICFactory.client;
@ -9,7 +6,6 @@ import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
import java.util.List;
import org.gcube.common.resources.gcore.GCoreEndpoint;
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.slf4j.Logger;
@ -17,7 +13,8 @@ import org.slf4j.LoggerFactory;
/**
* Discover the Social Networking Service in the Infrastructure.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
public class GcoreEndpointReaderSNL {
@ -30,34 +27,37 @@ public class GcoreEndpointReaderSNL {
/**
* Discover the gcore endpoint for the social networking service.
* @param scope the scope
* @throws Exception the exception
*/
public GcoreEndpointReaderSNL() throws Exception {
String currentScope = ScopeProvider.instance.get();
try {
SimpleQuery query = queryFor(GCoreEndpoint.class);
query.addCondition(String.format("$resource/Profile/ServiceClass/text() eq '%s'", SERVICE_CLASSE));
query.addCondition("$resource/Profile/DeploymentData/Status/text() eq 'ready'");
query.addCondition(String.format("$resource/Profile/ServiceName/text() eq '%s'", SERVICE_NAME));
query.setResult("$resource/Profile/AccessPoint/RunningInstanceInterfaces//Endpoint[@EntryName/string() eq \""+RESOURCE+"\"]/text()");
query.setResult(
"$resource/Profile/AccessPoint/RunningInstanceInterfaces//Endpoint[@EntryName/string() eq \""
+ RESOURCE + "\"]/text()");
DiscoveryClient<String> client = client();
List<String> endpoints = client.submit(query);
if (endpoints == null || endpoints.isEmpty())
throw new Exception("Cannot retrieve the GCoreEndpoint SERVICE_NAME: "+SERVICE_NAME +", SERVICE_CLASSE: " +SERVICE_CLASSE +", in scope: "+currentScope);
if(endpoints == null || endpoints.isEmpty()) {
throw new Exception("Cannot retrieve the GCoreEndpoint SERVICE_NAME: " + SERVICE_NAME
+ ", SERVICE_CLASSE: " + SERVICE_CLASSE + ", in scope: " + ContextUtils.getContext());
}
this.serviceBasePath = endpoints.get(0);
if(serviceBasePath == null)
throw new Exception("Endpoint:"+RESOURCE+", is null for SERVICE_NAME: "+SERVICE_NAME +", SERVICE_CLASSE: " +SERVICE_CLASSE +", in scope: "+currentScope);
throw new Exception("Endpoint:" + RESOURCE + ", is null for SERVICE_NAME: " + SERVICE_NAME
+ ", SERVICE_CLASSE: " + SERVICE_CLASSE + ", in scope: " + ContextUtils.getContext());
serviceBasePath = serviceBasePath.endsWith("/") ? serviceBasePath : serviceBasePath + "/";
} catch(Exception e) {
String error = "An error occurred during GCoreEndpoint discovery, SERVICE_NAME: "+SERVICE_NAME +", SERVICE_CLASSE: " +SERVICE_CLASSE +", in scope: "+currentScope +".";
String error = "An error occurred during GCoreEndpoint discovery, SERVICE_NAME: " + SERVICE_NAME
+ ", SERVICE_CLASSE: " + SERVICE_CLASSE + ", in scope: " + ContextUtils.getContext() + ".";
logger.error(error, e);
throw new Exception(error);
}
@ -69,4 +69,5 @@ public class GcoreEndpointReaderSNL {
public String getServiceBasePath() {
return serviceBasePath;
}
}

View File

@ -6,27 +6,21 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Actions to performa after a package has been correctly created on ckan.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* Actions to perform after a package has been correctly created on ckan.
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
public class PackageCreatePostActions extends Thread {
private String packageId;
private String context;
private String datasetUrl;
private String token;
private String username;
private boolean isApplication;
private JSONArray tags;
private String title;
public static final String ITEM_URL = "Item URL";
@ -39,22 +33,10 @@ public class PackageCreatePostActions extends Thread {
* @param tags
* @param title
*/
public PackageCreatePostActions(
String username,
boolean isApplication,
String datasetUrl,
String packageId,
String context,
String token,
JSONArray tags,
String title) {
public PackageCreatePostActions(String datasetUrl, String packageId, JSONArray tags, String title) {
super();
this.packageId = packageId;
this.datasetUrl = datasetUrl;
this.isApplication = isApplication;
this.context = context;
this.token = token;
this.username = username;
this.tags = tags;
this.title = title;
}
@ -63,28 +45,23 @@ public class PackageCreatePostActions extends Thread {
public void run() {
try {
ScopeProvider.instance.set(context);
SecurityTokenProvider.instance.set(token);
DataCatalogue utils = CatalogueUtils.getCatalogue();
String apiKey = isApplication ? CatalogueUtils.fetchSysAPI(context) : utils.getApiKeyFromUsername(username);
utils.setSearchableField(packageId, true);
DataCatalogue dataCatalogue = CatalogueUtils.getCatalogue();
String apiKey = CatalogueUtils.getApiKey();
dataCatalogue.setSearchableField(packageId, true);
// add also this information as custom field
if(datasetUrl == null)
datasetUrl = utils.getUnencryptedUrlFromDatasetIdOrName(packageId);
datasetUrl = dataCatalogue.getUnencryptedUrlFromDatasetIdOrName(packageId);
Map<String,List<String>> addField = new HashMap<String,List<String>>();
addField.put(ITEM_URL, Arrays.asList(datasetUrl));
utils.patchProductCustomFields(packageId, apiKey, addField, false);
dataCatalogue.patchProductCustomFields(packageId, apiKey, addField, false);
String fullNameUser = null;
if(!isApplication){
JSONObject profile = CatalogueUtils.getUserProfile(username);
String userFullName = ContextUtils.getUsername();
if(!ContextUtils.isApplication()) {
JSONObject profile = CatalogueUtils.getUserProfile();
JSONObject profileValues = (JSONObject) profile.get(Constants.RESULT_KEY);
fullNameUser = (String) profileValues.get(Constants.FULLNAME_IN_PROFILE_KEY);
}else{
fullNameUser = username;
userFullName = (String) profileValues.get(Constants.FULLNAME_IN_PROFILE_KEY);
}
List<String> tagsList = null;
@ -98,16 +75,8 @@ public class PackageCreatePostActions extends Thread {
}
// write notification post
WritePostCatalogueManagerThread threadWritePost =
new WritePostCatalogueManagerThread(
context,
title,
datasetUrl,
utils.isNotificationToUsersEnabled(),
tagsList,
fullNameUser,
token
);
WritePostCatalogueManagerThread threadWritePost = new WritePostCatalogueManagerThread(title, datasetUrl,
dataCatalogue.isNotificationToUsersEnabled(), tagsList, userFullName);
threadWritePost.start();
} catch(Exception e) {

View File

@ -12,7 +12,6 @@ import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang.math.NumberUtils;
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.common.scope.impl.ScopeBean.Type;
@ -27,18 +26,23 @@ import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.NamespaceCategory;
import org.geojson.GeoJsonObject;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.trentorise.opendata.jackan.model.CkanGroup;
/**
* Validate creation item requests utilities.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public class Validator {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Validator.class);
private static final Logger logger = LoggerFactory.getLogger(Validator.class);
private static final SimpleDateFormat DATE_SIMPLE = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat DATE_HOUR_MINUTES = new SimpleDateFormat("yyyy-MM-dd HH:mm");
@ -48,14 +52,11 @@ public class Validator {
* @param caller
* @throws Exception
*/
public static void checkResourcesInformation(JSONObject dataset, Caller caller) throws Exception {
public static void checkResourcesInformation(JSONObject dataset) throws Exception {
JSONArray resources = (JSONArray) dataset.get(Constants.RESOURCES_KEY);
if(resources == null || resources.isEmpty())
if(resources == null || resources.isEmpty()) {
return;
else{
} else {
Iterator it = resources.iterator();
while(it.hasNext()) {
JSONObject resource = (JSONObject) it.next();
@ -63,12 +64,12 @@ public class Validator {
String name = (String) resource.get(Constants.RESOURCE_NAME_KEY);
String url = (String) resource.get(Constants.RESOURCE_URL_KEY);
if(url == null || name == null || url.isEmpty() || name.isEmpty())
if(url == null || name == null || url.isEmpty() || name.isEmpty()) {
throw new Exception("Resources must have at least a name and an url field set!");
}
}
}
}
/**
@ -84,23 +85,22 @@ public class Validator {
* @return
* @throws Exception
*/
public static void checkBaseInformation(JSONObject dataset, Caller caller, boolean isAppRequest) throws Exception{
public static void checkBaseInformation(JSONObject dataset) throws Exception {
// check license
String licenseId = (String) dataset.get(Constants.LICENSE_KEY);
if(licenseId == null || licenseId.isEmpty())
throw new Exception("You must specify a license identifier to be attached to the item. License list can be retrieved invoking license methods");
throw new Exception(
"You must specify a license identifier to be attached to the item. License list can be retrieved invoking license methods");
// set author and author email
if(!isAppRequest){
JSONObject profile = CatalogueUtils.getUserProfile(caller.getClient().getId());
if(!ContextUtils.isApplication()) {
JSONObject profile = CatalogueUtils.getUserProfile();
JSONObject profileValues = (JSONObject) profile.get(Constants.RESULT_KEY);
dataset.put(Constants.AUTHOR_KEY, profileValues.get(Constants.FULLNAME_IN_PROFILE_KEY));
dataset.put(Constants.AUTHOR_EMAIL_KEY, profileValues.get(Constants.EMAIL_IN_PROFILE_KEY));
} else {
dataset.put(Constants.AUTHOR_KEY, caller.getClient().getId());
dataset.put(Constants.AUTHOR_KEY, ContextUtils.getUsername());
dataset.put(Constants.AUTHOR_EMAIL_KEY, CatalogueUtils.getCatalogue().getCatalogueEmail());
}
@ -112,22 +112,22 @@ public class Validator {
}
// owner organization must be specified if the token belongs to a VRE
String username = caller.getClient().getId();
ScopeBean scopeBean = new ScopeBean(ScopeProvider.instance.get());
String ownerOrgFromScope = scopeBean.name();
boolean isVREToken = scopeBean.is(Type.VRE);
String ownerOrg = (String) dataset.get(Constants.OWNER_ORG_KEY);
String organization = isVREToken ? ownerOrgFromScope.toLowerCase().replace(" ", "_").replace("-", "_") : ownerOrg != null ?
ownerOrg.toLowerCase().replace(" ", "_").replace("-", "_") : null;
String organization = isVREToken ? ownerOrgFromScope.toLowerCase().replace(" ", "_").replace("-", "_")
: ownerOrg != null ? ownerOrg.toLowerCase().replace(" ", "_").replace("-", "_") : null;
if(organization != null) {
if(!isAppRequest)
CatalogueUtils.checkRole(username, organization);
dataset.put(Constants.OWNER_ORG_KEY, organization);
if(!ContextUtils.isApplication()) {
CatalogueUtils.checkRole(organization);
}
dataset.put(Constants.OWNER_ORG_KEY, organization);
} else {
throw new Exception("You must specify the field '" + Constants.OWNER_ORG_KEY + "' in which the item should be published!");
}
else
throw new Exception("You must specify the field 'owner_org' in which the item should be published!");
}
@ -139,14 +139,23 @@ public class Validator {
* @return
* @throws Exception
*/
public static void validateAgainstProfile(JSONObject obj, Caller caller, List<String> profiles, boolean isApplication) throws Exception {
public static void validateAgainstProfile(JSONObject obj, List<String> profiles) throws Exception {
JSONArray extrasArrayOriginal = (JSONArray) obj.get(Constants.EXTRAS_KEY);
JSONArray groupsArrayOriginal = (JSONArray) obj.get(Constants.GROUPS_KEY);
JSONArray tagsArrayOriginal = (JSONArray) obj.get(Constants.TAGS_KEY);
if(extrasArrayOriginal == null || extrasArrayOriginal.isEmpty())
if(extrasArrayOriginal == null || extrasArrayOriginal.isEmpty()) {
throw new Exception("'extras' field is missing in context where metadata profile(s) are defined!");
}
if(groupsArrayOriginal == null) {
groupsArrayOriginal = new JSONArray();
}
if(tagsArrayOriginal == null) {
tagsArrayOriginal = new JSONArray();
}
// get the metadata profile specifying the type
CustomField metadataTypeCF = null;
@ -155,53 +164,55 @@ public class Validator {
while(iterator.hasNext()) {
JSONObject object = (JSONObject) iterator.next();
CustomField cf = new CustomField(object);
if(cf.getKey().equals(Constants.TYPE_KEY))
if(cf.getKey().equals(Constants.TYPE_KEY)) {
metadataTypeCF = cf;
else if(cf.getKey().equals(PackageCreatePostActions.ITEM_URL))
} else if(cf.getKey().equals(PackageCreatePostActions.ITEM_URL)) {
continue;
else
} else {
customFields.add(cf);
}
}
if(metadataTypeCF == null)
throw new Exception("'" + Constants.TYPE_KEY + "' extra field is missing in context where metadata profile(s) are defined!");
if(metadataTypeCF == null) {
throw new Exception("'" + Constants.TYPE_KEY
+ "' extra field is missing in context where metadata profile(s) are defined!");
}
if(groupsArrayOriginal == null)
groupsArrayOriginal = new JSONArray();
if(tagsArrayOriginal == null)
tagsArrayOriginal = new JSONArray();
// fetch the profile by metadata type specified above
MetadataFormat profile = null;
for(String profileName : profiles) {
profile = CatalogueUtils.getMetadataProfile(profileName);
if(profile.getType().equals(metadataTypeCF.getValue()))
if(profile.getType().equals(metadataTypeCF.getValue())) {
break;
else
} else {
profile = null;
}
}
if(profile == null)
throw new Exception("'" + Constants.TYPE_KEY + "' extra field's value specified as custom field doesn't match any of the profiles defined in this context!");
else{
if(profile == null) {
throw new Exception("'" + Constants.TYPE_KEY
+ "' extra field's value ('" + metadataTypeCF.getValue() +
"') specified as custom field doesn't match any of the profiles defined in this context!");
} else {
JSONArray extrasArrayUpdated = null;
List<MetadataField> metadataFields = profile.getMetadataFields();
if(metadataFields == null || metadataFields.isEmpty())
if(metadataFields == null || metadataFields.isEmpty()) {
extrasArrayUpdated = extrasArrayOriginal;
else{
} else {
extrasArrayUpdated = new JSONArray();
List<NamespaceCategory> categories = CatalogueUtils.getNamespaceCategories();
logger.debug("Retrieved namespaces are " + categories);
logger.debug("Retrieved namespaces are {}", categories);
List<String> categoriesIds = new ArrayList<String>(categories == null ? 0 : categories.size());
if(categories == null || categories.isEmpty())
logger.warn("No category defined in context " + ScopeProvider.instance.get());
else
for (NamespaceCategory metadataCategory : categories)
if(categories == null || categories.isEmpty()) {
logger.warn("No category defined in context {}", ScopeProvider.instance.get());
} else {
for(NamespaceCategory metadataCategory : categories) {
categoriesIds.add(metadataCategory.getId()); // save them later for matching with custom fields
}
}
// the list of already validated customFields
List<CustomField> validatedCustomFields = new ArrayList<CustomField>(customFields.size());
@ -209,7 +220,8 @@ public class Validator {
// keep track of mandatory fields and their cardinality
Map<String,Integer> fieldsMandatoryLowerBoundMap = new HashMap<String,Integer>(metadataFields.size());
Map<String,Integer> fieldsMandatoryUpperBoundMap = new HashMap<String,Integer>(metadataFields.size());
Map<String, Integer> numberFieldsMandatorySameKeyMap = new HashMap<String, Integer>(metadataFields.size());
Map<String,Integer> numberFieldsMandatorySameKeyMap = new HashMap<String,Integer>(
metadataFields.size());
// keep track of the groups that must be created AFTER validation but BEFORE item creation
List<String> groupsToCreateAfterValidation = new ArrayList<String>();
@ -220,27 +232,18 @@ public class Validator {
int categoryIdIndex = categoriesIds.indexOf(metadataField.getCategoryRef());
logger.debug("Found index for category " + metadataField.getCategoryRef() + " " + categoryIdIndex);
List<CustomField> validCFs = validateAgainstMetadataField(
metadataIndex,
categoryIdIndex,
customFields,
tagsArrayOriginal,
groupsArrayOriginal,
metadataField,
categories,
fieldsMandatoryLowerBoundMap,
fieldsMandatoryUpperBoundMap,
numberFieldsMandatorySameKeyMap,
groupsToCreateAfterValidation,
caller.getClient().getId(),
isApplication);
List<CustomField> validCFs = validateAgainstMetadataField(metadataIndex, categoryIdIndex,
customFields, tagsArrayOriginal, groupsArrayOriginal, metadataField, categories,
fieldsMandatoryLowerBoundMap, fieldsMandatoryUpperBoundMap, numberFieldsMandatorySameKeyMap,
groupsToCreateAfterValidation);
validatedCustomFields.addAll(validCFs);
metadataIndex++;
}
// check mandatory fields
Iterator<Entry<String, Integer>> iteratorLowerBounds = fieldsMandatoryLowerBoundMap.entrySet().iterator();
Iterator<Entry<String,Integer>> iteratorLowerBounds = fieldsMandatoryLowerBoundMap.entrySet()
.iterator();
while(iteratorLowerBounds.hasNext()) {
Map.Entry<java.lang.String,java.lang.Integer> entry = (Map.Entry<java.lang.String,java.lang.Integer>) iteratorLowerBounds
.next();
@ -248,15 +251,20 @@ public class Validator {
int upperBound = fieldsMandatoryUpperBoundMap.get(entry.getKey());
int inserted = numberFieldsMandatorySameKeyMap.get(entry.getKey());
logger.info("Field with key '" + entry.getKey() + "' has been found " + inserted + " times and its lower bound is " + lowerBound + " and upper bound " + upperBound);
logger.info("Field with key '" + entry.getKey() + "' has been found " + inserted
+ " times and its lower bound is " + lowerBound + " and upper bound " + upperBound);
if(inserted < lowerBound || inserted > upperBound)
throw new Exception("Field with key '" + entry.getKey() + "' is mandatory, but it's not present among the provided fields or its cardinality is not respected ([min = " + lowerBound + ", max=" + upperBound +"]).");
if(inserted < lowerBound || inserted > upperBound) {
throw new Exception("Field with key '" + entry.getKey()
+ "' is mandatory, but it's not present among the provided fields or its cardinality is not respected ([min = "
+ lowerBound + ", max=" + upperBound + "]).");
}
}
// if there are no tags, throw an exception
if(tagsArrayOriginal.isEmpty())
if(tagsArrayOriginal.isEmpty()) {
throw new Exception("Please define at least one tag for this item!");
}
// sort validated custom fields and add to the extrasArrayUpdated json array
Collections.sort(validatedCustomFields);
@ -284,7 +292,7 @@ public class Validator {
// create groups
for(String title : groupsToCreateAfterValidation) {
try {
CatalogueUtils.createGroupAsSysAdmin(title, title, "");
createGroupAsSysAdmin(title, title, "");
} catch(Exception e) {
logger.error("Failed to create group with title " + title, e);
}
@ -299,6 +307,15 @@ public class Validator {
}
/**
* Retrieve an instance of the library for the scope
* @param scope if it is null it is evaluated from the session
* @return
* @throws Exception
*/
public static CkanGroup createGroupAsSysAdmin(String title, String groupName, String description) throws Exception {
return CatalogueUtils.getCatalogue().createGroup(groupName, title, description);
}
/**
* Validate this field and generate a new value (or returns the same if there is nothing to update)
@ -315,19 +332,11 @@ public class Validator {
* @return
* @throws Exception
*/
private static List<CustomField> validateAgainstMetadataField(
int metadataIndex,
int categoryIndex,
List<CustomField> customFields,
JSONArray tagsArrayOriginal,
JSONArray groupsArrayOriginal,
MetadataField metadataField,
List<NamespaceCategory> categories,
Map<String, Integer> fieldsMandatoryLowerBoundMap,
Map<String, Integer> fieldsMandatoryUpperBoundMap,
Map<String, Integer> numberFieldsMandatorySameKeyMap,
List<String> groupToCreate,
String username, boolean isApplication) throws Exception {
private static List<CustomField> validateAgainstMetadataField(int metadataIndex, int categoryIndex,
List<CustomField> customFields, JSONArray tagsArrayOriginal, JSONArray groupsArrayOriginal,
MetadataField metadataField, List<NamespaceCategory> categories,
Map<String,Integer> fieldsMandatoryLowerBoundMap, Map<String,Integer> fieldsMandatoryUpperBoundMap,
Map<String,Integer> numberFieldsMandatorySameKeyMap, List<String> groupToCreate) throws Exception {
List<CustomField> toReturn = new ArrayList<CustomField>();
String metadataFieldName = metadataField.getCategoryFieldQName(); // get the qualified one, if any
@ -337,22 +346,19 @@ public class Validator {
while(iterator.hasNext()) {
CustomField cf = (CustomField) iterator.next();
if(cf.getKey().equals(metadataFieldName)) {
validate(cf, metadataField);
fieldsFoundWithThisKey++;
cf.setIndexCategory(categoryIndex);
cf.setIndexMetadataField(metadataIndex);
checkAsGroup(cf, metadataField, groupsArrayOriginal, groupToCreate, username, isApplication);
checkAsGroup(cf, metadataField, groupsArrayOriginal, groupToCreate);
checkAsTag(cf, metadataField, tagsArrayOriginal);
toReturn.add(cf);
iterator.remove();
}
}
// in case of mandatory fields, keep track of the number of times they appear
if(metadataField.getMandatory()) {
// lower bound
int lowerBound = 1;
if(fieldsMandatoryLowerBoundMap.containsKey(metadataFieldName))
@ -361,8 +367,9 @@ public class Validator {
// upper bound
boolean hasVocabulary = metadataField.getVocabulary() != null;
int upperBound = hasVocabulary ?
(metadataField.getVocabulary().isMultiSelection() ? metadataField.getVocabulary().getVocabularyFields().size() : 1) : 1;
int upperBound = hasVocabulary ? (metadataField.getVocabulary().isMultiSelection()
? metadataField.getVocabulary().getVocabularyFields().size()
: 1) : 1;
if(fieldsMandatoryUpperBoundMap.containsKey(metadataFieldName))
upperBound += fieldsMandatoryUpperBoundMap.get(metadataFieldName);
@ -374,7 +381,6 @@ public class Validator {
if(numberFieldsMandatorySameKeyMap.containsKey(metadataFieldName))
countPerFields += numberFieldsMandatorySameKeyMap.get(metadataFieldName);
numberFieldsMandatorySameKeyMap.put(metadataFieldName, countPerFields);
}
// if there was no field with this key and it was not mandatory, just add an entry of the kind {"key": "key-value", "value" : ""}.
@ -393,8 +399,8 @@ public class Validator {
* @param metadataField
* @param tagsArrayOriginal
*/
private static void checkAsTag(CustomField fieldToValidate,
MetadataField metadataField, JSONArray tagsArrayOriginal) {
private static void checkAsTag(CustomField fieldToValidate, MetadataField metadataField,
JSONArray tagsArrayOriginal) {
MetadataTagging tagging = metadataField.getTagging();
if(tagging != null) {
@ -437,8 +443,8 @@ public class Validator {
* @param isApplication
* @throws Exception
*/
private static void checkAsGroup(CustomField fieldToValidate,
MetadataField metadataField, JSONArray groupsArrayOriginal, List<String> groupToCreate, String username, boolean isApplication) throws Exception {
private static void checkAsGroup(CustomField fieldToValidate, MetadataField metadataField,
JSONArray groupsArrayOriginal, List<String> groupToCreate) throws Exception {
logger.debug("Custom field is " + fieldToValidate);
logger.debug("MetadataField field is " + metadataField);
@ -473,7 +479,8 @@ public class Validator {
JSONObject group = new JSONObject();
group.put("name", CatalogueUtilMethods.fromGroupTitleToName(title));
if(propagateUp) {
List<String> parents = CatalogueUtils.getGroupHierarchyNames(CatalogueUtilMethods.fromGroupTitleToName(title), username, isApplication);
List<String> parents = CatalogueUtils
.getGroupHierarchyNames(CatalogueUtilMethods.fromGroupTitleToName(title));
for(String parent : parents) {
JSONObject groupP = new JSONObject();
groupP.put("name", parent);
@ -500,11 +507,11 @@ public class Validator {
* @return
* @throws Exception
*/
private static void validate(CustomField fieldToValidate,
MetadataField metadataField) throws Exception {
private static void validate(CustomField fieldToValidate, MetadataField metadataField) throws Exception {
DataType dataType = metadataField.getDataType();
String regex = metadataField.getValidator() != null ? metadataField.getValidator().getRegularExpression() : null;
String regex = metadataField.getValidator() != null ? metadataField.getValidator().getRegularExpression()
: null;
boolean hasControlledVocabulary = metadataField.getVocabulary() != null;
String value = fieldToValidate.getValue();
String key = fieldToValidate.getKey();
@ -515,7 +522,8 @@ public class Validator {
if((value == null || value.isEmpty()))
if(metadataField.getMandatory() || hasControlledVocabulary)
throw new Exception("Mandatory field with name '" + key + "' doesn't have a value but it is mandatory or has a controlled vocabulary!");
throw new Exception("Mandatory field with name '" + key
+ "' doesn't have a value but it is mandatory or has a controlled vocabulary!");
else {
if(defaultValue != null && !defaultValue.isEmpty()) {
value = defaultValue;
@ -530,7 +538,8 @@ public class Validator {
case Text:
if(regex != null && !value.matches(regex))
throw new Exception("Field with key '" + key + "' doesn't match the provided regular expression (" + regex + ")!");
throw new Exception("Field with key '" + key + "' doesn't match the provided regular expression ("
+ regex + ")!");
if(hasControlledVocabulary) {
@ -547,7 +556,8 @@ public class Validator {
}
if(!match)
throw new Exception("Field with key '" + key + "' has a value '" + value + "' but it doesn't match any of the vocabulary's values ("+valuesVocabulary+")!");
throw new Exception("Field with key '" + key + "' has a value '" + value
+ "' but it doesn't match any of the vocabulary's values (" + valuesVocabulary + ")!");
}
@ -636,5 +646,4 @@ public class Validator {
}
}

View File

@ -20,71 +20,54 @@ import org.json.simple.parser.JSONParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Let the Product Catalogue Manager write a post in a VRE and alert there is a new product.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
public class WritePostCatalogueManagerThread extends Thread {
private static Logger logger = LoggerFactory.getLogger(WritePostCatalogueManagerThread.class);
private static final String APPLICATION_ID_CATALOGUE_MANAGER = "org.gcube.datacatalogue.ProductCatalogue";
private static final String NOTIFICATION_MESSAGE = "Dear members,<br>The item '$PRODUCT_TITLE' has been just published by $USER_FULLNAME.<br>You can find it here: $PRODUCT_URL <br>";
private static final String SOCIAL_SERVICE_APPLICATION_TOKEN = "/2/tokens/generate-application-token";
private static final String SOCIAL_SERVICE_WRITE_APPLICATION_POST = "/2/posts/write-post-app";
private static final String MEDIATYPE_JSON = "application/json";
private static Logger logger = LoggerFactory.getLogger(WritePostCatalogueManagerThread.class);
private String scope;
private String productTitle;
private String productName;
private String productUrl;
private boolean enableNotification;
private List<String> hashtags;
private String userFullName;
private String token;
/**
* @param token
* @param scope
* @param productTitle
* @param productUrl
* @param enableNotification
* @param hashtags
* @param userFullName
*/
public WritePostCatalogueManagerThread(
String scope,
String productTitle, String productUrl, boolean enableNotification,
List<String> hashtags, String userFullName, String token) {
public WritePostCatalogueManagerThread(String productName, String productUrl, boolean enableNotification,
List<String> hashtags, String userFullName) {
super();
this.scope = scope;
this.productTitle = productTitle;
this.productName = productName;
this.productUrl = productUrl;
this.enableNotification = enableNotification;
this.hashtags = hashtags;
this.userFullName = userFullName;
this.token = token;
}
@Override
public void run() {
try {
// set token and scope
ScopeProvider.instance.set(scope);
SecurityTokenProvider.instance.set(token);
logger.info("Started request to write application post "
+ "for new product created. Scope is " + scope + " and "
+ "token is " + token.substring(0, 10) + "****************");
logger.info(
"Started request to write application post for new product created. Scope is {} and token is {}****************",
ScopeProvider.instance.get(), SecurityTokenProvider.instance.get().substring(0, 10));
// write
writeProductPost(
productTitle,
productUrl,
userFullName,
hashtags,
enableNotification
);
writeProductPost();
} catch(Exception e) {
logger.error("Failed to write the post because of the following error ", e);
@ -101,32 +84,33 @@ public class WritePostCatalogueManagerThread extends Thread {
* @param hashtags a list of product's hashtags
* @throws Exception
*/
private static void writeProductPost(String productName, String productUrl, String userFullname, List<String> hashtags, boolean enablePostNotification) throws Exception{
private void writeProductPost() throws Exception {
// discover service endpoint for the social networking library
String currentScope = ScopeProvider.instance.get();
String tokenUser = SecurityTokenProvider.instance.get();
logger.info("Current scope for writeProductPost is " + currentScope + " and token is " + tokenUser.substring(0, 10) + "***************");
logger.debug("Current scope for writeProductPost is " + currentScope + " and token is "
+ tokenUser.substring(0, 10) + "***************");
GcoreEndpointReaderSNL socialService = new GcoreEndpointReaderSNL();
String basePath = socialService.getServiceBasePath();
if(basePath == null) {
logger.error("Unable to write a post because there is no social networking service available");
} else {
// check base path form
basePath = basePath.endsWith("/") ? basePath : basePath + "/";
try(CloseableHttpClient client = HttpClientBuilder.create().build();) {
String pathTokenApp = basePath + SOCIAL_SERVICE_APPLICATION_TOKEN + "?" + Constants.GCUBE_TOKEN_PARAMETER + "=" + tokenUser;
String pathTokenApp = basePath + SOCIAL_SERVICE_APPLICATION_TOKEN + "?"
+ Constants.GCUBE_TOKEN_PARAMETER + "=" + tokenUser;
String tokenApp = requireAppToken(client, pathTokenApp);
if(tokenApp != null) {
String pathWritePost = basePath + SOCIAL_SERVICE_WRITE_APPLICATION_POST + "?gcube-token=" + tokenApp;
writePost(client, pathWritePost, productName, productUrl, userFullname, hashtags, enablePostNotification);
String pathWritePost = basePath + SOCIAL_SERVICE_WRITE_APPLICATION_POST + "?gcube-token="
+ tokenApp;
writePost(client, pathWritePost, productName, productUrl, userFullName, hashtags,
enableNotification);
}
} catch(Exception e) {
@ -147,7 +131,8 @@ public class WritePostCatalogueManagerThread extends Thread {
String token = null;
try {
HttpResponse response = performRequest(client, path, "{\"app_id\":\"" + APPLICATION_ID_CATALOGUE_MANAGER + "\"}");
HttpResponse response = performRequest(client, path,
"{\"app_id\":\"" + APPLICATION_ID_CATALOGUE_MANAGER + "\"}");
int statusTokenGenerate = response.getStatusLine().getStatusCode();
@ -178,7 +163,8 @@ public class WritePostCatalogueManagerThread extends Thread {
logger.error("Failed to retrieve application token", e);
}
logger.info("Returning app token " + (token != null ? token.substring(0, 10) + "*************************" : null));
logger.info(
"Returning app token " + (token != null ? token.substring(0, 10) + "*************************" : null));
return token;
}
@ -192,13 +178,14 @@ public class WritePostCatalogueManagerThread extends Thread {
* @param hashtags
*/
@SuppressWarnings("unchecked")
private static void writePost(CloseableHttpClient client, String path, String productName, String productUrl, String userFullname, List<String> hashtags,
boolean enablePostNotification) {
private static void writePost(CloseableHttpClient client, String path, String productName, String productUrl,
String userFullname, List<String> hashtags, boolean enablePostNotification) {
try {
// replace
String message = NOTIFICATION_MESSAGE.replace("$PRODUCT_TITLE", productName).replace("$PRODUCT_URL", productUrl).replace("$USER_FULLNAME", userFullname);
String message = NOTIFICATION_MESSAGE.replace("$PRODUCT_TITLE", productName)
.replace("$PRODUCT_URL", productUrl).replace("$USER_FULLNAME", userFullname);
if(hashtags != null && !hashtags.isEmpty())
for(String hashtag : hashtags) {
@ -234,7 +221,8 @@ public class WritePostCatalogueManagerThread extends Thread {
Header lastLocation = locations[locations.length - 1];
String realLocation = lastLocation.getValue();
logger.debug("New location is " + realLocation);
writePost(client, realLocation, productName, productUrl, userFullname, hashtags, enablePostNotification);
writePost(client, realLocation, productName, productUrl, userFullname, hashtags,
enablePostNotification);
} else
throw new RuntimeException("Failed to write the post");
@ -273,14 +261,13 @@ public class WritePostCatalogueManagerThread extends Thread {
* @throws IOException
* @throws ClientProtocolException
*/
private static HttpResponse performRequest(CloseableHttpClient client, String path, String entity) throws ClientProtocolException, IOException{
private static HttpResponse performRequest(CloseableHttpClient client, String path, String entity)
throws ClientProtocolException, IOException {
HttpPost request = new HttpPost(path);
StringEntity stringEntity = new StringEntity(entity);
stringEntity.setContentType(MEDIATYPE_JSON);
request.setEntity(stringEntity);
return client.execute(request);
}
}

View File

@ -10,18 +10,15 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
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.datacatalogue.catalogue.utils.CatalogueUtils;
import org.gcube.datacatalogue.catalogue.utils.Constants;
import org.gcube.datacatalogue.catalogue.utils.Delegator;
@Path(Constants.GROUPS)
/**
* Groups service endpoint.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* All checks are demanded to CKAN
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
public class Group {
@ -29,26 +26,16 @@ public class Group {
@Path(Constants.SHOW_METHOD)
@Produces(MediaType.APPLICATION_JSON)
public String show(@Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_show
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
boolean isApplication = CatalogueUtils.isApplicationToken(caller);
return Delegator.delegateGet(caller, context, Constants.GROUP_SHOW, uriInfo, isApplication);
return Delegator.delegateGet(Constants.GROUP_SHOW, uriInfo);
}
@GET
@Path(Constants.LIST_METHOD)
@Produces(MediaType.APPLICATION_JSON)
public String list(@Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_list
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
boolean isApplication = CatalogueUtils.isApplicationToken(caller);
return Delegator.delegateGet(caller, context, Constants.GROUP_LIST, uriInfo, isApplication);
return Delegator.delegateGet(Constants.GROUP_LIST, uriInfo);
}
@POST
@ -56,12 +43,8 @@ public class Group {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String create(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_create
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return Delegator.delegatePost(caller, context, Constants.GROUP_CREATE, json, uriInfo, false);
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.group_create
return Delegator.delegatePost(Constants.GROUP_CREATE, json, uriInfo);
}
@DELETE
@ -69,12 +52,8 @@ public class Group {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String delete(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_delete
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return Delegator.delegatePost(caller, context, Constants.GROUP_DELETE, json, uriInfo, false);
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.group_delete
return Delegator.delegatePost(Constants.GROUP_DELETE, json, uriInfo);
}
@DELETE
@ -82,12 +61,8 @@ public class Group {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String purge(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_purge
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return Delegator.delegatePost(caller, context, Constants.GROUP_PURGE, json, uriInfo, false);
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.group_purge
return Delegator.delegatePost(Constants.GROUP_PURGE, json, uriInfo);
}
@POST
@ -95,12 +70,8 @@ public class Group {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String update(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_update
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return Delegator.delegatePost(caller, context, Constants.GROUP_UPDATE, json, uriInfo, false);
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.group_update
return Delegator.delegatePost(Constants.GROUP_UPDATE, json, uriInfo);
}
@POST
@ -108,12 +79,8 @@ public class Group {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String patch(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_patch
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return Delegator.delegatePost(caller, context, Constants.GROUP_PATCH, json, uriInfo, false);
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.group_patch
return Delegator.delegatePost(Constants.GROUP_PATCH, json, uriInfo);
}
}

View File

@ -7,18 +7,16 @@ import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.catalogue.entities.CatalogueItem;
import org.gcube.datacatalogue.catalogue.utils.CatalogueUtils;
import org.gcube.datacatalogue.catalogue.utils.Constants;
import org.gcube.datacatalogue.catalogue.utils.ContextUtils;
import org.gcube.datacatalogue.catalogue.utils.Delegator;
import org.gcube.datacatalogue.catalogue.utils.PackageCreatePostActions;
import org.gcube.datacatalogue.catalogue.utils.Validator;
@ -29,6 +27,7 @@ import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.trentorise.opendata.jackan.model.CkanDataset;
@ -36,300 +35,291 @@ import eu.trentorise.opendata.jackan.model.CkanDataset;
@Path(Constants.ITEMS)
/**
* Items service endpoint.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
public class Item {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Item.class);
private static final Logger logger = LoggerFactory.getLogger(Item.class);
private static final String ID_NAME = "id";
private static final String ID_PATH_PARAM = "id";
private void applicationChecks(String datasetId, String authorizationErroMessage) throws Exception {
if(ContextUtils.isApplication()) {
logger.debug("Application Token Request");
DataCatalogue dataCatalogue = CatalogueUtils.getCatalogue();
CkanDataset dataset = dataCatalogue.getDataset(datasetId, CatalogueUtils.fetchSysAPI());
String organization = CatalogueUtilMethods.getCKANOrganization();
if(organization.equalsIgnoreCase(dataset.getOrganization().getName())
&& ContextUtils.getUsername().equals(dataset.getAuthor())) {
return;
}
throw new Exception(authorizationErroMessage);
}
}
@GET
@Path(Constants.SHOW_METHOD)
@Path("{" + ID_PATH_PARAM + "}")
@Produces(MediaType.APPLICATION_JSON)
public String show(@Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_show
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
boolean isApplication = CatalogueUtils.isApplicationToken(caller);
String username = caller.getClient().getId();
if(!isApplication)
return Delegator.delegateGet(caller, context, Constants.ITEM_SHOW, uriInfo, false);
else{
public String show(@PathParam(ID_PATH_PARAM) String itemId, @Context UriInfo uriInfo) {
try {
DataCatalogue utils = CatalogueUtils.getCatalogue();
String organization = CatalogueUtilMethods.getOrganizationNameFromScope(context);
String datasetId = null;
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters(false);
List<String> ids = queryParams.get("id");
if(ids == null || ids.isEmpty())
throw new Exception("'id' field is missing!");
datasetId = ids.get(0);
CkanDataset item = utils.getDataset(datasetId, CatalogueUtils.fetchSysAPI(context));
if(organization.equalsIgnoreCase(item.getOrganization().getName()) && username.equals(item.getAuthor())){
return Delegator.delegateGet(caller, context, Constants.ITEM_SHOW, uriInfo, true);
}else
throw new Exception("You are not authorized to access this item");
if(itemId.compareTo(Constants.SHOW_METHOD)==0) {
return show(uriInfo);
}
CatalogueItem item = new CatalogueItem();
item.setId(itemId);
return item.read();
} catch(Exception e) {
logger.error("", e);
return CatalogueUtils.createJSONOnFailure(e.toString());
}
}
public String show(@Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_show
try {
String datasetId = CatalogueUtils.getIdFromUriInfo(ID_NAME, uriInfo);
applicationChecks(datasetId, "You are not authorized to access this item");
} catch(Exception e) {
logger.error("", e);
return CatalogueUtils.createJSONOnFailure(e.toString());
}
return Delegator.delegateGet(Constants.ITEM_SHOW, uriInfo);
}
@SuppressWarnings("unchecked")
@POST
@Path(Constants.CREATE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Deprecated
public String oldCreate(String json, @Context UriInfo uriInfo) {
return this.create(json, uriInfo);
}
@SuppressWarnings("unchecked")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String create(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_create
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId(); // in case of application token is the label of the token
String context = ScopeProvider.instance.get();
boolean isApplication = CatalogueUtils.isApplicationToken(caller);
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.package_create
try {
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject) parser.parse(json);
// check base information (and set them if needed)
Validator.checkBaseInformation(obj, caller, isApplication);
Validator.checkBaseInformation(obj);
// check resources information (name and url must be there)
Validator.checkResourcesInformation(obj, caller);
Validator.checkResourcesInformation(obj);
// Check if there are profiles here
List<String> profiles = CatalogueUtils.getProfilesNames();
if(profiles != null && !profiles.isEmpty())
Validator.validateAgainstProfile(obj, caller, profiles, isApplication);
if(profiles != null && !profiles.isEmpty()) {
Validator.validateAgainstProfile(obj, profiles);
}
obj = (JSONObject)parser.parse(Delegator.delegatePost(caller, context, Constants.ITEM_CREATE, obj.toJSONString(), uriInfo, isApplication));
JSONParser resultParser = new JSONParser();
JSONObject createdJSONObject = (JSONObject) resultParser
.parse(Delegator.delegatePost(Constants.ITEM_CREATE, obj.toJSONString(), uriInfo));
// after creation, if it is ok ...
if((boolean)obj.get(Constants.SUCCESS_KEY)){
if((boolean) createdJSONObject.get(Constants.SUCCESS_KEY)) {
JSONObject result = (JSONObject)obj.get(Constants.RESULT_KEY);
DataCatalogue utils = CatalogueUtils.getCatalogue();
JSONObject result = (JSONObject) createdJSONObject.get(Constants.RESULT_KEY);
DataCatalogue dataCatalogue = CatalogueUtils.getCatalogue();
// add also this information as custom field
String datasetUrl = utils.getUnencryptedUrlFromDatasetIdOrName((String)(result.get(Constants.DATASET_KEY)));
String datasetUrl = dataCatalogue
.getUnencryptedUrlFromDatasetIdOrName((String) (result.get(Constants.DATASET_KEY)));
if(datasetUrl != null) {
JSONObject itemUrl = new JSONObject();
itemUrl.put(Constants.EXTRA_KEY, PackageCreatePostActions.ITEM_URL);
itemUrl.put(Constants.EXTRA_VALUE, datasetUrl);
((JSONArray)((JSONObject)obj.get(Constants.RESULT_KEY)).get(Constants.EXTRAS_KEY)).add(itemUrl);
((JSONArray) ((JSONObject) createdJSONObject.get(Constants.RESULT_KEY)).get(Constants.EXTRAS_KEY))
.add(itemUrl);
}
PackageCreatePostActions packagePostActions = new PackageCreatePostActions(
username,
isApplication,
datasetUrl,
PackageCreatePostActions packagePostActions = new PackageCreatePostActions(datasetUrl,
(String) (result.get(Constants.DATASET_KEY)),
context,
SecurityTokenProvider.instance.get(),
(JSONArray) (result.get(Constants.TAGS_KEY)),
(String)(result.get(Constants.TITLE_KEY))
);
(String) (result.get(Constants.TITLE_KEY)));
packagePostActions.start();
}
return obj.toJSONString();
return createdJSONObject.toJSONString();
} catch(Exception e) {
logger.error("Something went wrong... ", e);
if(e instanceof ParseException)
if(e instanceof ParseException) {
return CatalogueUtils.createJSONOnFailure("Failed to parse incoming json!");
else
} else {
return CatalogueUtils.createJSONOnFailure(e.toString());
}
}
}
@DELETE
@Path("{" + ID_PATH_PARAM + "}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String delete(@PathParam(ID_PATH_PARAM) String itemId, String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.package_delete
try {
if(itemId.compareTo(Constants.DELETE_METHOD)==0) {
itemId = CatalogueUtils.getIdFromJSONString(ID_NAME, json);
}
applicationChecks(itemId, "You cannot delete this item");
} catch(Exception e) {
logger.error("", e);
if(e instanceof ParseException) {
return CatalogueUtils.createJSONOnFailure("Failed to parse incoming json!");
} else {
return CatalogueUtils.createJSONOnFailure(e.toString());
}
}
return Delegator.delegatePost(Constants.ITEM_DELETE, json, uriInfo);
}
/* @DELETE
@Path(Constants.DELETE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String delete(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_delete
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
String username = caller.getClient().getId();
boolean isApplication = CatalogueUtils.isApplicationToken(caller);
if(!isApplication)
return Delegator.delegatePost(caller, context, Constants.ITEM_DELETE, json, uriInfo, isApplication);
else{
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.package_delete
try {
DataCatalogue utils = CatalogueUtils.getCatalogue();
// in this case we check the author has been filled with the same qualifier of this token: the same qualifier can be used in two different contexts
String organization = CatalogueUtilMethods.getOrganizationNameFromScope(context);
String datasetId = null;
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject)parser.parse(json);
datasetId = (String)obj.get("id");
if(datasetId == null || datasetId.isEmpty())
throw new Exception("'id' field is missing!");
CkanDataset item = utils.getDataset(datasetId, CatalogueUtils.fetchSysAPI(context));
if(organization.equalsIgnoreCase(item.getOrganization().getName()) && username.equals(item.getAuthor())){
return Delegator.delegatePost(caller, context, Constants.ITEM_DELETE, json, uriInfo, true);
}else
throw new Exception("You cannot delete this item");
String datasetId = CatalogueUtils.getIdFromJSONString(ID_NAME, json);
applicationChecks(datasetId, "You cannot delete this item");
} catch(Exception e) {
logger.error("Something went wrong... ", e);
if(e instanceof ParseException)
logger.error("", e);
if(e instanceof ParseException) {
return CatalogueUtils.createJSONOnFailure("Failed to parse incoming json!");
else
} else {
return CatalogueUtils.createJSONOnFailure(e.toString());
}
}
return Delegator.delegatePost(Constants.ITEM_DELETE, json, uriInfo);
}
}*/
@DELETE
@Path(Constants.PURGE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String purge(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.dataset_purge
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
String username = caller.getClient().getId();
try {
DataCatalogue dataCatalogue = CatalogueUtils.getCatalogue();
String username = ContextUtils.getUsername();
if(!dataCatalogue.isSysAdmin(username)) {
String datasetId = CatalogueUtils.getIdFromJSONString(ID_NAME, json);
if(ContextUtils.isApplication()) {
applicationChecks(datasetId, "You cannot purge this item");
} else {
DataCatalogue utils = CatalogueUtils.getCatalogue();
boolean isApplication = CatalogueUtils.isApplicationToken(caller);
String userApiKey = dataCatalogue.getApiKeyFromUsername(ContextUtils.getUsername());
CkanDataset item = dataCatalogue.getDataset(datasetId, userApiKey);
if(isApplication){
// in this case we check the author has been filled with the same qualifier of this token: the same qualifier can be used in two different contexts
String organization = CatalogueUtilMethods.getOrganizationNameFromScope(context);
String datasetId = null;
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject)parser.parse(json);
datasetId = (String)obj.get("id");
if(datasetId == null || datasetId.isEmpty())
throw new Exception("'id' field is missing!");
CkanDataset item = utils.getDataset(datasetId, CatalogueUtils.fetchSysAPI(context));
if(organization.equalsIgnoreCase(item.getOrganization().getName()) && username.equals(item.getAuthor())){
return Delegator.delegatePost(caller, context, Constants.ITEM_PURGE, json, uriInfo, true);
}else
throw new Exception("You cannot purge this item");
}
else{
// if sysadmin, just invoke ckan
if(utils.isSysAdmin(username)){
logger.debug("User " + caller.getClient().getId() + " seems a sysadmin");
return Delegator.delegatePost(caller, context, Constants.ITEM_PURGE, json, uriInfo, false);
}
else{
String datasetId = null;
String ownerId = null;
String organization = null;
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject)parser.parse(json);
datasetId = (String)obj.get("id");
if(datasetId == null || datasetId.isEmpty())
throw new Exception("'id' field is missing!");
String userApiKey = utils.getApiKeyFromUsername(username);
CkanDataset item = utils.getDataset(datasetId, userApiKey);
ownerId = item.getCreatorUserId();
organization = item.getOrganization().getName();
String ownerId = item.getCreatorUserId();
String organization = item.getOrganization().getName();
// check user role here
RolesCkanGroupOrOrg roleInOrganization = RolesCkanGroupOrOrg.convertFromCapacity(utils.getRoleOfUserInOrganization(username, organization, userApiKey));
RolesCkanGroupOrOrg roleInOrganization = RolesCkanGroupOrOrg.convertFromCapacity(
dataCatalogue.getRoleOfUserInOrganization(username, organization, userApiKey));
boolean purged = false;
if(roleInOrganization.equals(RolesCkanGroupOrOrg.MEMBER)) {
throw new Exception("You have not enough priviliges to delete item with id " + datasetId);
} else if(roleInOrganization.equals(RolesCkanGroupOrOrg.ADMIN)) {
purged = utils.deleteProduct(datasetId, userApiKey, true);
purged = dataCatalogue.deleteProduct(datasetId, userApiKey, true);
} else {
// we have an editor here; just check she owns the dataset
String userIdCkan = utils.getUserFromApiKey(userApiKey).getId();
if(ownerId.equals(userIdCkan))
purged = utils.deleteProduct(datasetId, userApiKey, true);
else
String userIdCkan = dataCatalogue.getUserFromApiKey(userApiKey).getId();
if(ownerId.equals(userIdCkan)) {
purged = dataCatalogue.deleteProduct(datasetId, userApiKey, true);
} else {
throw new Exception("Editors can only remove their own items!");
}
}
return CatalogueUtils.createJSONObjectMin(purged, null).toJSONString();
}
}
}
catch (Exception e) {
logger.error("Something went wrong... ", e);
if(e instanceof ParseException)
} catch(Exception e) {
logger.error("", e);
if(e instanceof ParseException) {
return CatalogueUtils.createJSONOnFailure("Failed to parse incoming json!");
else
} else {
return CatalogueUtils.createJSONOnFailure(e.toString());
}
}
return Delegator.delegatePost(Constants.ITEM_PURGE, json, uriInfo);
}
@POST
@Path(Constants.UPDATE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String update(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.package_update
try {
String datasetId = CatalogueUtils.getIdFromJSONString(ID_NAME, json);
applicationChecks(datasetId, "You cannot update this item");
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject) parser.parse(json);
// check base information (and set them if needed)
Validator.checkBaseInformation(obj);
// check resources information (name and url must be there)
Validator.checkResourcesInformation(obj);
// Check if there are profiles here
List<String> profiles = CatalogueUtils.getProfilesNames();
if(profiles != null && !profiles.isEmpty()) {
Validator.validateAgainstProfile(obj, profiles);
}
return Delegator.delegatePost(Constants.ITEM_UPDATE, json, uriInfo);
} catch (Exception e) {
logger.error("", e);
if(e instanceof ParseException) {
return CatalogueUtils.createJSONOnFailure("Failed to parse incoming json!");
} else {
return CatalogueUtils.createJSONOnFailure(e.toString());
}
}
}
// TODO PROFILE VALIDATION MUST BE PERFORMED HERE AS WELL
// @POST
// @Path(Constants.UPDATE_METHOD)
// @Consumes(MediaType.APPLICATION_JSON)
// @Produces(MediaType.APPLICATION_JSON)
// public String update(String json){
//
//
// // 1) Check if there are profiles here
// // 2) If there are profiles: match the record against them
// // 3) Else submit it
//
// // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_update
// Caller caller = AuthorizationProvider.instance.get();
// String context = ScopeProvider.instance.get();
// return CatalogueUtils.delegatePost(caller, context, Constants.ITEM_UPDATE, json);
//
// }
// @POST
// @Path(Constants.PATCH_METHOD)
// @Consumes(MediaType.APPLICATION_JSON)
// @Produces(MediaType.APPLICATION_JSON)
// public String patch(String json){
//
//
// // 1) Check if there are profiles here
// // 2) If there are profiles: match the record against them
// // 3) Else submit it
//
// // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_patch
// Caller caller = AuthorizationProvider.instance.get();
// String context = ScopeProvider.instance.get();
// return CatalogueUtils.delegatePost(caller, context, Constants.ITEM_PATCH, json);
//
// }
/*
@POST
@Path(Constants.PATCH_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String patch(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.package_patch
try {
return Delegator.delegatePost(Constants.ITEM_PATCH, json, uriInfo);
} catch (Exception e) {
logger.error("", e);
if(e instanceof ParseException) {
return CatalogueUtils.createJSONOnFailure("Failed to parse incoming json!");
} else {
return CatalogueUtils.createJSONOnFailure(e.toString());
}
}
}
*/
}

View File

@ -14,29 +14,28 @@ import org.gcube.datacatalogue.catalogue.utils.Constants;
import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.NamespaceCategory;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Path(Constants.PROFILES)
/**
* Items profiles service endpoint.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
public class ItemProfile {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(ItemProfile.class);
private static final Logger logger = LoggerFactory.getLogger(ItemProfile.class);
@SuppressWarnings("unchecked")
@GET
@Path(Constants.PROFILES_NAMES_SHOW)
@Produces(MediaType.APPLICATION_JSON)
public String showNames() {
String context = ScopeProvider.instance.get();
logger.debug("Incoming request for context " + context);
// get the names as list
JSONObject json = CatalogueUtils.createJSONObjectMin(true, null);
try {
List<String> names = CatalogueUtils.getProfilesNames();
JSONArray array = new JSONArray();
@ -50,7 +49,6 @@ public class ItemProfile {
} catch(Exception e) {
json = CatalogueUtils.createJSONObjectMin(false, e.getMessage());
}
return json.toJSONString();
}
@ -60,27 +58,22 @@ public class ItemProfile {
public String showSource(
//@DefaultValue(MediaType.APPLICATION_XML) @HeaderParam("Accept") String accept,
@QueryParam("name") String profileName) throws Exception {
String context = ScopeProvider.instance.get();
logger.debug("Incoming request for context/name " + context + "/" + profileName);
// TODO Check how this mapping xml-> json works
/*if(accept.equals(MediaType.APPLICATION_JSON)){
org.json.JSONObject xmlJSONObj = XML.toJSONObject(content);
return xmlJSONObj.toString(PRETTY_PRINT_INDENT_FACTOR);
}*/
return CatalogueUtils.getProfileSource(profileName);
}
@GET
@Path(Constants.NAMESPACES_SHOW)
@Produces(MediaType.APPLICATION_JSON)
@SuppressWarnings("unchecked")
public String showNamespaces() throws Exception {
// get the names as list
JSONObject json = CatalogueUtils.createJSONObjectMin(true, null);
JSONArray namespacesJson = new JSONArray();
@ -98,7 +91,6 @@ public class ItemProfile {
} catch(Exception e) {
json = CatalogueUtils.createJSONObjectMin(false, e.getMessage());
}
return json.toJSONString();
}

View File

@ -7,10 +7,6 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
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.datacatalogue.catalogue.utils.CatalogueUtils;
import org.gcube.datacatalogue.catalogue.utils.Constants;
import org.gcube.datacatalogue.catalogue.utils.Delegator;
@ -18,7 +14,8 @@ import org.gcube.datacatalogue.catalogue.utils.Delegator;
@Path(Constants.LICENSES)
/**
* Licenses service endpoint.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
public class License {
@ -26,13 +23,8 @@ public class License {
@Path(Constants.LIST_METHOD)
@Produces(MediaType.APPLICATION_JSON)
public String show(@Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.license_list
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
boolean isApplication = CatalogueUtils.isApplicationToken(caller);
return Delegator.delegateGet(caller, context, Constants.LICENSES_SHOW, uriInfo, isApplication);
return Delegator.delegateGet(Constants.LICENSES_SHOW, uriInfo);
}
}

View File

@ -1,7 +1,5 @@
package org.gcube.datacatalogue.catalogue.ws;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
@ -10,80 +8,68 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
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.datacatalogue.catalogue.utils.CatalogueUtils;
import org.gcube.datacatalogue.catalogue.utils.Constants;
import org.gcube.datacatalogue.catalogue.utils.ContextUtils;
import org.gcube.datacatalogue.catalogue.utils.Delegator;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.server.utils.CatalogueUtilMethods;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.trentorise.opendata.jackan.model.CkanOrganization;
@Path(Constants.ORGANIZATIONS)
/**
* Organizations service endpoint.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
public class Organization {
private static final Logger logger = LoggerFactory.getLogger(Organization.class);
private static final String ID_NAME = "id";
private void applicationChecks(String organizationId, String authorizationErroMessage) throws Exception {
if(ContextUtils.isApplication()) {
logger.debug("Application Token Request");
DataCatalogue dataCatalogue = CatalogueUtils.getCatalogue();
String organization = CatalogueUtilMethods.getCKANOrganization();
CkanOrganization fetchedOrganization = dataCatalogue.getOrganizationByName(organizationId);
if(organization.equalsIgnoreCase(fetchedOrganization.getName())) {
return;
}
throw new Exception(authorizationErroMessage);
}
}
@GET
@Path(Constants.SHOW_METHOD)
@Produces(MediaType.APPLICATION_JSON)
public String show(@Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_show
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
boolean isApplication = CatalogueUtils.isApplicationToken(caller);
if(!isApplication)
return Delegator.delegateGet(caller, context, Constants.ORGANIZATION_SHOW, uriInfo, false);
else{
try {
DataCatalogue utils = CatalogueUtils.getCatalogue();
String organization = CatalogueUtilMethods.getOrganizationNameFromScope(context);
String organizationId = null;
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters(false);
List<String> ids = queryParams.get("id");
if(ids == null || ids.isEmpty())
throw new Exception("'id' field is missing!");
organizationId = ids.get(0);
CkanOrganization fetchedOrganization = utils.getOrganizationByName(organizationId);
if(organization.equalsIgnoreCase(fetchedOrganization.getName())){
return Delegator.delegateGet(caller, context, Constants.ORGANIZATION_SHOW, uriInfo, true);
}else
throw new Exception("You are not authorized to access this organization");
String organizationId = CatalogueUtils.getIdFromUriInfo(ID_NAME, uriInfo);
applicationChecks(organizationId, "You are not authorized to access this organization");
} catch(Exception e) {
logger.error("", e);
return CatalogueUtils.createJSONOnFailure(e.toString());
}
}
return Delegator.delegateGet(Constants.ORGANIZATION_SHOW, uriInfo);
}
@GET
@Path(Constants.LIST_METHOD)
@Produces(MediaType.APPLICATION_JSON)
public String organizationList(@Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_list
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
boolean isApplication = CatalogueUtils.isApplicationToken(caller);
return Delegator.delegateGet(caller, context, Constants.ORGANIZATION_LIST, uriInfo, isApplication);
return Delegator.delegateGet(Constants.ORGANIZATION_LIST, uriInfo);
}
@ -92,12 +78,8 @@ public class Organization {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String create(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_create
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return Delegator.delegatePost(caller, context, Constants.ORGANIZATION_CREATE, json, uriInfo, false);
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.organization_create
return Delegator.delegatePost(Constants.ORGANIZATION_CREATE, json, uriInfo);
}
@DELETE
@ -105,12 +87,8 @@ public class Organization {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String delete(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_delete
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return Delegator.delegatePost(caller, context, Constants.ORGANIZATION_DELETE, json, uriInfo, false);
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.organization_delete
return Delegator.delegatePost(Constants.ORGANIZATION_DELETE, json, uriInfo);
}
@DELETE
@ -118,12 +96,8 @@ public class Organization {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String purge(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_create
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return Delegator.delegatePost(caller, context, Constants.ORGANIZATION_PURGE, json, uriInfo, false);
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.organization_purge
return Delegator.delegatePost(Constants.ORGANIZATION_PURGE, json, uriInfo);
}
@POST
@ -131,11 +105,8 @@ public class Organization {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String update(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_update
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return Delegator.delegatePost(caller, context, Constants.ORGANIZATION_UPDATE, json, uriInfo, false);
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.organization_update
return Delegator.delegatePost(Constants.ORGANIZATION_UPDATE, json, uriInfo);
}
@ -144,12 +115,8 @@ public class Organization {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String patch(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_patch
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return Delegator.delegatePost(caller, context, Constants.ORGANIZATION_PATCH, json, uriInfo, false);
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.organization_patch
return Delegator.delegatePost(Constants.ORGANIZATION_PATCH, json, uriInfo);
}
}

View File

@ -1,8 +1,5 @@
package org.gcube.datacatalogue.catalogue.ws;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@ -12,22 +9,17 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
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.common.scope.impl.ScopeBean;
import org.gcube.datacatalogue.catalogue.utils.CatalogueUtils;
import org.gcube.datacatalogue.catalogue.utils.Constants;
import org.gcube.datacatalogue.catalogue.utils.ContextUtils;
import org.gcube.datacatalogue.catalogue.utils.Delegator;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.server.utils.CatalogueUtilMethods;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.trentorise.opendata.jackan.model.CkanDataset;
@ -36,49 +28,45 @@ import eu.trentorise.opendata.jackan.model.CkanResource;
@Path(Constants.RESOURCES)
/**
* Resource service endpoint.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
public class Resource {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Resource.class);
private static final Logger logger = LoggerFactory.getLogger(Resource.class);
private static final String ID_NAME = "id";
private static final String PACKAGE_ID_NAME = "package_id";
private void applicationChecks(String datasetId, String authorizationErroMessage) throws Exception {
if(ContextUtils.isApplication()) {
logger.debug("Application Token Request");
DataCatalogue dataCatalogue = CatalogueUtils.getCatalogue();
CkanDataset dataset = dataCatalogue.getDataset(datasetId, CatalogueUtils.fetchSysAPI());
String organization = CatalogueUtilMethods.getCKANOrganization();
if(organization.equalsIgnoreCase(dataset.getOrganization().getName())
&& ContextUtils.getUsername().equals(dataset.getAuthor())) {
return;
}
throw new Exception(authorizationErroMessage);
}
}
@GET
@Path(Constants.SHOW_METHOD)
@Produces(MediaType.APPLICATION_JSON)
public String show(@Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.resource_show
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
String username = caller.getClient().getId();
boolean isApplication = CatalogueUtils.isApplicationToken(caller);
if(isApplication){
try {
DataCatalogue utils = CatalogueUtils.getCatalogue();
String organization = CatalogueUtilMethods.getOrganizationNameFromScope(context);
String resourceId = null;
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters(false);
List<String> ids = queryParams.get("id");
if(ids == null || ids.isEmpty())
throw new Exception("'id' field is missing!");
CkanResource resource = utils.getResource(resourceId, CatalogueUtils.fetchSysAPI(context));
CkanDataset item = utils.getDataset(resource.getPackageId(), CatalogueUtils.fetchSysAPI(context));
if(organization.equalsIgnoreCase(item.getOrganization().getName()) && username.equals(item.getAuthor())){
return Delegator.delegateGet(caller, context, Constants.RESOURCE_SHOW, uriInfo, true);
}else
throw new Exception("You are not authorized to access this resource");
String resourceId = CatalogueUtils.getIdFromUriInfo(ID_NAME, uriInfo);
CkanResource resource = CatalogueUtils.getCatalogue().getResource(resourceId, CatalogueUtils.fetchSysAPI());
applicationChecks(resource.getPackageId(), "You are not authorized to access this resource");
} catch(Exception e) {
logger.error("", e);
return CatalogueUtils.createJSONOnFailure(e.toString());
}
}
return Delegator.delegateGet(caller, context, Constants.RESOURCE_SHOW, uriInfo, isApplication);
return Delegator.delegateGet(Constants.RESOURCE_SHOW, uriInfo);
}
@POST
@ -86,93 +74,39 @@ public class Resource {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String create(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.resource_create
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
String username = caller.getClient().getId();
boolean isApplication = CatalogueUtils.isApplicationToken(caller);
if(!isApplication)
return Delegator.delegatePost(caller, context, Constants.RESOURCE_CREATE, json, uriInfo, isApplication);
else{
try {
DataCatalogue utils = CatalogueUtils.getCatalogue();
// in this case we check the author has been filled with the same qualifier of this token: the same qualifier can be used in two different contexts
String organization = CatalogueUtilMethods.getOrganizationNameFromScope(ScopeProvider.instance.get());
String datasetId = null;
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject)parser.parse(json);
datasetId = (String)obj.get("package_id"); // within the resource it is defined this way
if(datasetId == null || datasetId.isEmpty())
throw new Exception("'id' field is missing!");
CkanDataset item = utils.getDataset(datasetId, CatalogueUtils.fetchSysAPI(context));
if(organization.equalsIgnoreCase(item.getOrganization().getName()) && username.equals(item.getAuthor())){
return Delegator.delegatePost(caller, context, Constants.RESOURCE_CREATE, json, uriInfo, true);
}else
throw new Exception("You cannot add a resource to this item");
String datasetId = CatalogueUtils.getIdFromJSONString(PACKAGE_ID_NAME, json);
applicationChecks(datasetId, "You cannot add a resource to this item");
} catch(Exception e) {
logger.error("Something went wrong... ", e);
if(e instanceof ParseException)
logger.error("", e);
if(e instanceof ParseException) {
return CatalogueUtils.createJSONOnFailure("Failed to parse incoming json!");
else
} else {
return CatalogueUtils.createJSONOnFailure(e.toString());
}
}
return Delegator.delegatePost(Constants.RESOURCE_CREATE, json, uriInfo);
}
@POST
@Path(Constants.CREATE_METHOD)
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public String create(
FormDataMultiPart multiPart, @Context UriInfo uriInfo,
@Context final HttpServletRequest request
){
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
String username = caller.getClient().getId();
boolean isApplication = CatalogueUtils.isApplicationToken(caller);
if(!isApplication)
return Delegator.delegatePost(caller, context, Constants.RESOURCE_CREATE, multiPart, uriInfo, false);
else{
public String create(FormDataMultiPart multiPart, @Context UriInfo uriInfo,
@Context final HttpServletRequest request) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.resource_create
try {
DataCatalogue utils = CatalogueUtils.getCatalogue();
// in this case we check the author has been filled with the same qualifier of this token: the same qualifier can be used in two different contexts
ScopeBean bean = new ScopeBean(ScopeProvider.instance.get());
String organization = bean.name().toLowerCase().replace(" ", "_").replace("-", "_");
String datasetId = null;
datasetId = (String)multiPart.getField("package_id").getValue(); // within the resource it is defined this way
if(datasetId == null || datasetId.isEmpty())
throw new Exception("'id' field is missing!");
CkanDataset item = utils.getDataset(datasetId, CatalogueUtils.fetchSysAPI(context));
if(organization.equalsIgnoreCase(item.getOrganization().getName()) && username.equals(item.getAuthor())){
return Delegator.delegatePost(caller, context, Constants.RESOURCE_CREATE, multiPart, uriInfo, true);
}else
throw new Exception("You cannot add a resource to this item");
String datasetId = (String) multiPart.getField(PACKAGE_ID_NAME).getValue(); // within the resource it is defined this way
if(datasetId == null || datasetId.isEmpty()) {
throw new Exception("'" + PACKAGE_ID_NAME +"' field is missing!");
}
applicationChecks(datasetId, "You cannot add a resource to this item");
} catch(Exception e) {
logger.error("Something went wrong... ", e);
if(e instanceof ParseException)
return CatalogueUtils.createJSONOnFailure("Failed to parse incoming json!");
else
logger.error("", e);
return CatalogueUtils.createJSONOnFailure(e.toString());
}
}
return Delegator.delegatePost(Constants.RESOURCE_CREATE, multiPart, uriInfo);
}
@DELETE
@ -180,47 +114,20 @@ public class Resource {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String delete(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.resource_delete
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
String username = caller.getClient().getId();
boolean isApplication = CatalogueUtils.isApplicationToken(caller);
if(!isApplication)
return Delegator.delegatePost(caller, context, Constants.RESOURCE_DELETE, json, uriInfo, false);
else{
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.resource_delete
try {
DataCatalogue utils = CatalogueUtils.getCatalogue();
// in this case we check the author has been filled with the same qualifier of this token: the same qualifier can be used in two different contexts
ScopeBean bean = new ScopeBean(ScopeProvider.instance.get());
String organization = bean.name().toLowerCase().replace(" ", "_").replace("-", "_");
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject)parser.parse(json);
String resourceId = (String)obj.get("id"); // within the resource it is defined this way
if(resourceId == null || resourceId.isEmpty())
throw new Exception("'id' field is missing!");
CkanResource resource = utils.getResource(resourceId, CatalogueUtils.fetchSysAPI(context));
CkanDataset item = utils.getDataset(resource.getPackageId(), CatalogueUtils.fetchSysAPI(context));
if(organization.equalsIgnoreCase(item.getOrganization().getName()) && username.equals(item.getAuthor())){
return Delegator.delegatePost(caller, context, Constants.RESOURCE_DELETE, json, uriInfo, true);
}else
throw new Exception("You cannot delete this resource");
String resourceId = CatalogueUtils.getIdFromJSONString(ID_NAME, json);
CkanResource resource = CatalogueUtils.getCatalogue().getResource(resourceId, CatalogueUtils.fetchSysAPI());
applicationChecks(resource.getPackageId(), "You cannot delete this resource");
} catch(Exception e) {
logger.error("Something went wrong... ", e);
if(e instanceof ParseException)
logger.error("", e);
if(e instanceof ParseException) {
return CatalogueUtils.createJSONOnFailure("Failed to parse incoming json!");
else
} else {
return CatalogueUtils.createJSONOnFailure(e.toString());
}
}
return Delegator.delegatePost(Constants.RESOURCE_DELETE, json, uriInfo);
}
@POST
@ -228,47 +135,20 @@ public class Resource {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String update(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.resource_update
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
String username = caller.getClient().getId();
boolean isApplication = CatalogueUtils.isApplicationToken(caller);
if(!isApplication)
return Delegator.delegatePost(caller, context, Constants.RESOURCE_UPDATE, json, uriInfo, false);
else{
try {
DataCatalogue utils = CatalogueUtils.getCatalogue();
// in this case we check the author has been filled with the same qualifier of this token: the same qualifier can be used in two different contexts
ScopeBean bean = new ScopeBean(ScopeProvider.instance.get());
String organization = bean.name().toLowerCase().replace(" ", "_").replace("-", "_");
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject)parser.parse(json);
String resourceId = (String)obj.get("id"); // within the resource it is defined this way
if(resourceId == null || resourceId.isEmpty())
throw new Exception("'id' field is missing!");
CkanResource resource = utils.getResource(resourceId, CatalogueUtils.fetchSysAPI(context));
CkanDataset item = utils.getDataset(resource.getPackageId(), CatalogueUtils.fetchSysAPI(context));
if(organization.equalsIgnoreCase(item.getOrganization().getName()) && username.equals(item.getAuthor())){
return Delegator.delegatePost(caller, context, Constants.RESOURCE_UPDATE, json, uriInfo, true);
}else
throw new Exception("You cannot update this resource");
String resourceId = CatalogueUtils.getIdFromJSONString(ID_NAME, json);
CkanResource resource = CatalogueUtils.getCatalogue().getResource(resourceId, CatalogueUtils.fetchSysAPI());
applicationChecks(resource.getPackageId(), "You cannot update this resource");
} catch(Exception e) {
logger.error("Something went wrong... ", e);
if(e instanceof ParseException)
logger.error("", e);
if(e instanceof ParseException) {
return CatalogueUtils.createJSONOnFailure("Failed to parse incoming json!");
else
} else {
return CatalogueUtils.createJSONOnFailure(e.toString());
}
}
return Delegator.delegatePost(Constants.RESOURCE_UPDATE, json, uriInfo);
}
@POST
@ -276,48 +156,20 @@ public class Resource {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String patch(String json, @Context UriInfo uriInfo) {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.resource_patch
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
String username = caller.getClient().getId();
boolean isApplication = CatalogueUtils.isApplicationToken(caller);
if(!isApplication)
return Delegator.delegatePost(caller, context, Constants.RESOURCE_PATCH, json, uriInfo, false);
else{
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.resource_patch
try {
DataCatalogue utils = CatalogueUtils.getCatalogue();
// in this case we check the author has been filled with the same qualifier of this token: the same qualifier can be used in two different contexts
ScopeBean bean = new ScopeBean(ScopeProvider.instance.get());
String organization = bean.name().toLowerCase().replace(" ", "_").replace("-", "_");
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject)parser.parse(json);
String resourceId = (String)obj.get("id"); // within the resource it is defined this way
if(resourceId == null || resourceId.isEmpty())
throw new Exception("'id' field is missing!");
CkanResource resource = utils.getResource(resourceId, CatalogueUtils.fetchSysAPI(context));
CkanDataset item = utils.getDataset(resource.getPackageId(), CatalogueUtils.fetchSysAPI(context));
if(organization.equalsIgnoreCase(item.getOrganization().getName()) && username.equals(item.getAuthor())){
return Delegator.delegatePost(caller, context, Constants.RESOURCE_PATCH, json, uriInfo, true);
}else
throw new Exception("You cannot patch this resource");
String resourceId = CatalogueUtils.getIdFromJSONString(ID_NAME, json);
CkanResource resource = CatalogueUtils.getCatalogue().getResource(resourceId, CatalogueUtils.fetchSysAPI());
applicationChecks(resource.getPackageId(), "You cannot patch this resource");
} catch(Exception e) {
logger.error("Something went wrong... ", e);
if(e instanceof ParseException)
logger.error("", e);
if(e instanceof ParseException) {
return CatalogueUtils.createJSONOnFailure("Failed to parse incoming json!");
else
} else {
return CatalogueUtils.createJSONOnFailure(e.toString());
}
}
return Delegator.delegatePost(Constants.RESOURCE_PATCH, json, uriInfo);
}
}

View File

@ -10,9 +10,6 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
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.datacatalogue.catalogue.utils.Constants;
import org.gcube.datacatalogue.catalogue.utils.Delegator;
@ -20,7 +17,8 @@ import org.gcube.datacatalogue.catalogue.utils.Delegator;
@Path(Constants.USERS)
/**
* User service endpoint.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
* @author Costantino Perciante (ISTI - CNR)
* @author Luca Frosini (ISTI - CNR)
*/
public class User {
@ -28,11 +26,8 @@ public class User {
@Path(Constants.SHOW_METHOD)
@Produces(MediaType.TEXT_PLAIN)
public String show(@Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.user_show
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return Delegator.delegateGet(caller, context, Constants.USER_SHOW, uriInfo, false);
return Delegator.delegateGet(Constants.USER_SHOW, uriInfo);
}
@ -41,11 +36,8 @@ public class User {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String create(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.user_create
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return Delegator.delegatePost(caller, context, Constants.USER_CREATE, json, uriInfo, false);
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.user_create
return Delegator.delegatePost(Constants.USER_CREATE, json, uriInfo);
}
@ -54,11 +46,8 @@ public class User {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String delete(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.user_delete
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return Delegator.delegatePost(caller, context, Constants.USER_DELETE, json, uriInfo, false);
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.user_delete
return Delegator.delegatePost(Constants.USER_DELETE, json, uriInfo);
}
@ -67,11 +56,8 @@ public class User {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String update(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.user_update
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return Delegator.delegatePost(caller, context, Constants.USER_UPDATE, json, uriInfo, false);
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.user_update
return Delegator.delegatePost(Constants.USER_UPDATE, json, uriInfo);
}

View File

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
monitoring="autodetect" dynamicConfig="true">
<diskStore path="/home/gcube/tomcat/tmp" />
<cache name="profile_readers" maxEntriesLocalHeap="10" eternal="false"
timeToIdleSeconds="3600" timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LFU" transactionalMode="off">
<persistence strategy="none" />
</cache>
<cache name="profile_users" maxEntriesLocalHeap="1000"
maxEntriesLocalDisk="1000" diskSpoolBufferSizeMB="20" eternal="false"
timeToIdleSeconds="3600" timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LFU" transactionalMode="off">
<persistence strategy="localTempSwap" />
</cache>
</ehcache>

View File

@ -1,6 +1,4 @@
import java.util.HashMap;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
@ -14,8 +12,6 @@ import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.Closea
import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.HttpClientBuilder;
import eu.trentorise.opendata.jackan.internal.org.apache.http.util.EntityUtils;
/**
* An example of publishing in the data catalogue.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)

View File

@ -4,13 +4,11 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import javax.cache.Cache;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.catalogue.beans.resource.CustomField;
import org.gcube.datacatalogue.catalogue.utils.CachesManager;
import org.gcube.datacatalogue.catalogue.utils.CatalogueUtils;
import org.gcube.datacatalogue.catalogue.utils.Constants;
import org.gcube.datacatalogue.metadatadiscovery.DataCalogueMetadataFormatReader;
import org.gcube.datacatalogue.metadatadiscovery.bean.MetadataProfile;
@ -20,8 +18,6 @@ import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.junit.Test;
public class JavaTests {
//@Test
@ -66,7 +62,6 @@ public class JavaTests {
}
//@Test
public void testSorting() {
@ -96,21 +91,19 @@ public class JavaTests {
}
//@Test
@Test
public void testEHCache() throws Exception {
ScopeProvider.instance.set("/gcube/devNext/NextNext");
Cache profilesCache = CachesManager.getCache(CachesManager.PROFILES_READERS_CACHE);
Cache<String,DataCalogueMetadataFormatReader> readerCache = CachesManager.getReaderCache();
String context = ScopeProvider.instance.get();
List<String> toReturn = new ArrayList<String>();
DataCalogueMetadataFormatReader reader;
if(profilesCache.isKeyInCache(context))
reader = (DataCalogueMetadataFormatReader) profilesCache.get(context).getObjectValue();
else{
if(readerCache.containsKey(context)){
reader = readerCache.get(context);
}else {
reader = new DataCalogueMetadataFormatReader();
profilesCache.put(new Element(context, reader));
readerCache.put(context, reader);
}
Thread.sleep(1000 * 60);

View File

@ -45,9 +45,7 @@ public class TestJersey extends JerseyTest {
JSONObject obj = new JSONObject();
obj.put("test", "value");
final JSONObject createResource = target("api/resources/create/")
.request()
.accept(MediaType.APPLICATION_JSON)
final JSONObject createResource = target("api/resources/create/").request().accept(MediaType.APPLICATION_JSON)
.post(Entity.json(obj), JSONObject.class);
logger.info(createResource.toJSONString());
}
@ -55,17 +53,12 @@ public class TestJersey extends JerseyTest {
//@Test
public void testFile() throws ParseException, IOException {
FileDataBodyPart fileDataBodyPart = new FileDataBodyPart("uploadFile",
new File("/Users/costantinoperciante/Desktop/rilascio_tess.doc"));
final MultiPart multipart = new FormDataMultiPart()
.field("foo", "bar")
.bodyPart(fileDataBodyPart);
final MultiPart multipart = new FormDataMultiPart().field("foo", "bar").bodyPart(fileDataBodyPart);
final Response createResource =
target("api/resources/create/")
.request()
final Response createResource = target("api/resources/create/").request()
.post(Entity.entity(multipart, multipart.getMediaType()));
logger.info(createResource.toString());
//
@ -75,17 +68,12 @@ public class TestJersey extends JerseyTest {
//@Test
public void testProfilesNames() throws ParseException, IOException {
FileDataBodyPart fileDataBodyPart = new FileDataBodyPart("uploadFile",
new File("/Users/costantinoperciante/Desktop/rilascio_tess.doc"));
final MultiPart multipart = new FormDataMultiPart()
.field("foo", "bar")
.bodyPart(fileDataBodyPart);
final MultiPart multipart = new FormDataMultiPart().field("foo", "bar").bodyPart(fileDataBodyPart);
final Response createResource =
target("api/resources/create/")
.request()
final Response createResource = target("api/resources/create/").request()
.post(Entity.entity(multipart, multipart.getMediaType()));
logger.info(createResource.toString());
//
@ -95,11 +83,8 @@ public class TestJersey extends JerseyTest {
//@Test
public void testProfileNames() throws ParseException, IOException {
final String profiles =
target("api/profiles/profile_names/")
.queryParam("context", "/gcube/devNext/NextNext")
.request()
.get(String.class);
final String profiles = target("api/profiles/profile_names/").queryParam("context", "/gcube/devNext/NextNext")
.request().get(String.class);
logger.info("Response is " + profiles);
@ -108,17 +93,12 @@ public class TestJersey extends JerseyTest {
//@Test
public void testProfileByName() throws ParseException, IOException {
final String profiles =
target("api/profiles/profile/")
.queryParam("context", "/gcube/devNext/NextNext")
.queryParam("name", "SoBigData.eu: Dataset Metadata NextNext")
.request(MediaType.APPLICATION_JSON)
final String profiles = target("api/profiles/profile/").queryParam("context", "/gcube/devNext/NextNext")
.queryParam("name", "SoBigData.eu: Dataset Metadata NextNext").request(MediaType.APPLICATION_JSON)
.get(String.class);
logger.info("Response is " + profiles);
}
}

View File

@ -0,0 +1,121 @@
package org.gcube.datacatalogue.catalogue;
/**
*
*/
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import org.gcube.common.authorization.client.Constants;
import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
import org.gcube.common.authorization.library.AuthorizationEntry;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.ClientInfo;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Luca Frosini (ISTI - CNR)
*
*/
public class ScopedTest {
private static final Logger logger = LoggerFactory.getLogger(ScopedTest.class);
protected static final String PROPERTIES_FILENAME = "token.properties";
private static final String GCUBE_VARNAME = "GCUBE";
public static final String GCUBE;
private static final String GCUBE_DEVNEXT_VARNAME = "GCUBE_DEVNEXT";
public static final String GCUBE_DEVNEXT;
private static final String GCUBE_DEVNEXT_NEXTNEXT_VARNAME = "GCUBE_DEVNEXT_NEXTNEXT";
public static final String GCUBE_DEVNEXT_NEXTNEXT;
public static final String GCUBE_DEVSEC_VARNAME = "GCUBE_DEVSEC";
public static final String GCUBE_DEVSEC;
public static final String GCUBE_DEVSEC_DEVVRE_VARNAME = "GCUBE_DEVSEC_DEVVRE";
public static final String GCUBE_DEVSEC_DEVVRE;
private static final String GCUBE_DEVNEXT_ANOTHER_USER_VARNAME = "GCUBE_DEVNEXT_ANOTHER_USER";
public static final String GCUBE_DEVNEXT_ANOTHER_USER;
private static final String GCUBE_DEVVRE_ANOTHER_USER_VARNAME = "GCUBE_DEVVRE_ANOTHER_USER";
public static final String GCUBE_DEVVRE_ANOTHER_USER;
public static final String DEFAULT_TEST_SCOPE;
public static final String PARENT_DEFAULT_TEST_SCOPE;
public static final String DEFAULT_TEST_SCOPE_ANOTHER_USER;
public static final String ALTERNATIVE_TEST_SCOPE;
static {
Properties properties = new Properties();
InputStream input = ScopedTest.class.getClassLoader().getResourceAsStream(PROPERTIES_FILENAME);
try {
// load the properties file
properties.load(input);
} catch (IOException e) {
throw new RuntimeException(e);
}
GCUBE = properties.getProperty(GCUBE_VARNAME);
GCUBE_DEVNEXT = properties.getProperty(GCUBE_DEVNEXT_VARNAME);
GCUBE_DEVNEXT_NEXTNEXT = properties.getProperty(GCUBE_DEVNEXT_NEXTNEXT_VARNAME);
GCUBE_DEVSEC = properties.getProperty(GCUBE_DEVSEC_VARNAME);
GCUBE_DEVSEC_DEVVRE = properties.getProperty(GCUBE_DEVSEC_DEVVRE_VARNAME);
GCUBE_DEVNEXT_ANOTHER_USER = properties.getProperty(GCUBE_DEVNEXT_ANOTHER_USER_VARNAME);
GCUBE_DEVVRE_ANOTHER_USER = properties.getProperty(GCUBE_DEVVRE_ANOTHER_USER_VARNAME);
DEFAULT_TEST_SCOPE = GCUBE_DEVSEC_DEVVRE;
PARENT_DEFAULT_TEST_SCOPE = GCUBE_DEVSEC;
DEFAULT_TEST_SCOPE_ANOTHER_USER = GCUBE_DEVVRE_ANOTHER_USER;
ALTERNATIVE_TEST_SCOPE = GCUBE;
}
public static String getCurrentScope(String token) throws ObjectNotFound, Exception{
AuthorizationEntry authorizationEntry = Constants.authorizationService().get(token);
String context = authorizationEntry.getContext();
logger.info("Context of token {} is {}", token, context);
return context;
}
public static void setContext(String token) throws ObjectNotFound, Exception{
SecurityTokenProvider.instance.set(token);
AuthorizationEntry authorizationEntry = Constants.authorizationService().get(token);
ClientInfo clientInfo = authorizationEntry.getClientInfo();
String qualifier = authorizationEntry.getQualifier();
Caller caller = new Caller(clientInfo, qualifier);
AuthorizationProvider.instance.set(caller);
ScopeProvider.instance.set(getCurrentScope(token));
}
@BeforeClass
public static void beforeClass() throws Exception{
setContext(DEFAULT_TEST_SCOPE);
}
@AfterClass
public static void afterClass() throws Exception{
SecurityTokenProvider.instance.reset();
ScopeProvider.instance.reset();
}
}

View File

@ -0,0 +1,23 @@
package org.gcube.datacatalogue.catalogue.entities;
import org.gcube.datacatalogue.catalogue.ScopedTest;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CatalogueItemTest extends ScopedTest {
private static final Logger logger = LoggerFactory.getLogger(CatalogueItemTest.class);
@Test
public void read() {
String id = "3e7b6924-7851-49fc-a08a-bd8a86d4af62";
CatalogueItem catalogueItem = new CatalogueItem();
catalogueItem.setId(id);
String res = catalogueItem.read();
logger.debug(res);
}
}

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{0}: %msg%n</pattern>
</encoder>
</appender>
<logger name="org.gcube" level="INFO" />
<logger name="org.gcube.datacatalogue" level="TRACE" />
<root level="WARN">
<appender-ref ref="STDOUT" />
</root>
</configuration>