1599 lines
53 KiB
Java
1599 lines
53 KiB
Java
package org.gcube.datacatalogue.utillibrary.server;
|
|
|
|
import static com.google.common.base.Preconditions.checkArgument;
|
|
import static com.google.common.base.Preconditions.checkNotNull;
|
|
|
|
import java.net.URLEncoder;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.ListIterator;
|
|
import java.util.Map;
|
|
import java.util.Map.Entry;
|
|
import java.util.Set;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
import org.apache.http.HttpResponse;
|
|
import org.apache.http.HttpStatus;
|
|
import org.apache.http.client.methods.HttpGet;
|
|
import org.apache.http.client.methods.HttpPost;
|
|
import org.apache.http.entity.ContentType;
|
|
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.scope.impl.ScopeBean;
|
|
import org.gcube.common.scope.impl.ScopeBean.Type;
|
|
import org.gcube.datacatalogue.utillibrary.ckan.ExtendCkanClient;
|
|
import org.gcube.datacatalogue.utillibrary.ckan.MarshUnmarshCkanObject;
|
|
import org.gcube.datacatalogue.utillibrary.ckan.MarshUnmarshCkanObject.METHOD;
|
|
import org.gcube.datacatalogue.utillibrary.db.DBCaller;
|
|
import org.gcube.datacatalogue.utillibrary.gcat.GCatCaller;
|
|
import org.gcube.datacatalogue.utillibrary.server.DataCatalogueRunningCluster.ACCESS_LEVEL_TO_CATALOGUE_PORTLET;
|
|
import org.gcube.datacatalogue.utillibrary.server.utils.CKANConveter;
|
|
import org.gcube.datacatalogue.utillibrary.server.utils.CatalogueUtilMethods;
|
|
import org.gcube.datacatalogue.utillibrary.server.utils.GCubeUtils;
|
|
import org.gcube.datacatalogue.utillibrary.server.utils.GcubeContext;
|
|
import org.gcube.datacatalogue.utillibrary.server.utils.url.EntityContext;
|
|
import org.gcube.datacatalogue.utillibrary.shared.LandingPages;
|
|
import org.gcube.datacatalogue.utillibrary.shared.ResourceBean;
|
|
import org.gcube.datacatalogue.utillibrary.shared.RolesCkanGroupOrOrg;
|
|
import org.gcube.datacatalogue.utillibrary.shared.State;
|
|
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset;
|
|
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanGroup;
|
|
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanLicense;
|
|
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanOrganization;
|
|
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanPair;
|
|
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanResource;
|
|
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanUser;
|
|
import org.gcube.datacatalogue.utillibrary.shared.jackan.model.exceptions.JackanException;
|
|
import org.json.simple.JSONArray;
|
|
import org.json.simple.JSONObject;
|
|
import org.json.simple.parser.JSONParser;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
/**
|
|
* This is the Ckan Utils implementation class.
|
|
*
|
|
* revisited by
|
|
* @author Francesco Mangiacrapa at ISTI-CNR
|
|
*
|
|
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
|
|
*/
|
|
public class DataCatalogueImpl implements DataCatalogue {
|
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(DataCatalogueImpl.class);
|
|
|
|
private String CKAN_CATALOGUE_URL;
|
|
private String CKAN_DB_NAME;
|
|
private String CKAN_DB_USER;
|
|
private String CKAN_DB_PASSWORD;
|
|
private String CKAN_DB_URL;
|
|
private Integer CKAN_DB_PORT;
|
|
private String PORTLET_URL_FOR_SCOPE;
|
|
private String SOLR_URL;
|
|
private String CKAN_TOKEN_SYS;
|
|
private String CKAN_EMAIL;
|
|
private String URI_RESOLVER_URL;
|
|
private boolean MANAGE_PRODUCT_BUTTON;
|
|
private boolean SOCIAL_POST;
|
|
private boolean ALERT_USERS_ON_POST_CREATION;
|
|
private String CONTEXT;
|
|
private Map<String, String> extendRoleInOrganization;
|
|
|
|
public Map<ACCESS_LEVEL_TO_CATALOGUE_PORTLET, String> mapAccessURLToCatalogue;
|
|
|
|
|
|
private static final String CATALOGUE_TAB_ENDING_URL = "/catalogue";
|
|
|
|
// gCat client
|
|
private GCatCaller gCatCaller;
|
|
|
|
// db client
|
|
private DBCaller dbCaller;
|
|
|
|
// ckan client
|
|
private ExtendCkanClient ckanCaller;
|
|
|
|
// hashmap for ckan api keys
|
|
private ConcurrentHashMap<String, CKANTokenBean> apiKeysMap;
|
|
|
|
//http ckan caller
|
|
//private DirectCkanCaller directCkanCaller; //is not needed anymore?
|
|
|
|
// apikey bean expires after X minutes in the above map
|
|
private static final int EXPIRE_KEY_TIME = 60 * 60 * 1000;
|
|
|
|
|
|
/**
|
|
* The ckan catalogue url and database will be discovered in this scope.
|
|
*
|
|
* @param scope the scope
|
|
* @throws Exception if unable to find datacatalogue info
|
|
*/
|
|
public DataCatalogueImpl(String scope) throws Exception{
|
|
|
|
DataCatalogueRunningCluster runningInstance = new DataCatalogueRunningCluster(scope);
|
|
|
|
// save information
|
|
CKAN_DB_URL = runningInstance.getDatabaseHosts().get(0).trim();
|
|
CKAN_DB_PORT = runningInstance.getDatabasePorts().get(0);
|
|
CKAN_DB_NAME = runningInstance.getDataBaseName().trim();
|
|
CKAN_DB_USER = runningInstance.getDataBaseUser().trim();
|
|
CKAN_DB_PASSWORD = runningInstance.getDataBasePassword().trim();
|
|
|
|
CKAN_TOKEN_SYS = runningInstance.getSysAdminToken().trim();
|
|
CKAN_EMAIL = runningInstance.getEmailCatalogue().trim();
|
|
|
|
CKAN_CATALOGUE_URL = runningInstance.getDataCatalogueUrl().get(0).trim();
|
|
PORTLET_URL_FOR_SCOPE = runningInstance.getPortletUrl().trim();
|
|
mapAccessURLToCatalogue = runningInstance.getMapAccessURLToCatalogue();
|
|
MANAGE_PRODUCT_BUTTON = runningInstance.isManageProductEnabled();
|
|
URI_RESOLVER_URL = runningInstance.getUrlResolver();
|
|
SOCIAL_POST = runningInstance.isSocialPostEnabled();
|
|
ALERT_USERS_ON_POST_CREATION = runningInstance.isAlertEnabled();
|
|
SOLR_URL = runningInstance.getUrlSolr();
|
|
|
|
LOG.info("In the scope: "+scope+", I read the catalogue URL: " + CKAN_CATALOGUE_URL);
|
|
|
|
// build the clients
|
|
gCatCaller = new GCatCaller(CKAN_CATALOGUE_URL);
|
|
dbCaller = new DBCaller(CKAN_DB_URL, CKAN_DB_PORT, CKAN_DB_NAME, CKAN_DB_USER, CKAN_DB_PASSWORD);
|
|
ckanCaller = new ExtendCkanClient(CKAN_CATALOGUE_URL);
|
|
//directCkanCaller = new DirectCkanCaller(CKAN_CATALOGUE_URL); //is not needed anymore?
|
|
// init map
|
|
apiKeysMap = new ConcurrentHashMap<String, CKANTokenBean>();
|
|
// save the context
|
|
CONTEXT = scope;
|
|
// extended roles
|
|
extendRoleInOrganization = runningInstance.getExtendRoleInOrganization();
|
|
}
|
|
|
|
/**
|
|
* The ckan catalogue url and database will be discovered in this scope.
|
|
*
|
|
* @param scope the scope
|
|
* @param sysAuthentication if true perform the sys authentication
|
|
* @throws Exception if unable to find datacatalogue info
|
|
*/
|
|
public DataCatalogueImpl(String scope, boolean sysAuthentication) throws Exception{
|
|
this(scope);
|
|
|
|
if(sysAuthentication)
|
|
ckanCaller = new ExtendCkanClient(CKAN_CATALOGUE_URL, CKAN_TOKEN_SYS);
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getCatalogueUrl()
|
|
*/
|
|
@Override
|
|
public String getCatalogueUrl() {
|
|
return CKAN_CATALOGUE_URL;
|
|
}
|
|
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getPortletUrl()
|
|
*/
|
|
@Override
|
|
public String getPortletUrl() {
|
|
|
|
//PATCHED By Francesco
|
|
ScopeBean context = new ScopeBean(CONTEXT);
|
|
|
|
if(context.is(Type.INFRASTRUCTURE)) {
|
|
LOG.info("Working with the {} scope returning the path read from GR 'Ckan-Porltet': {}", Type.INFRASTRUCTURE.toString(), PORTLET_URL_FOR_SCOPE);
|
|
return PORTLET_URL_FOR_SCOPE;
|
|
}
|
|
|
|
String vreNameLower = context.name().toLowerCase();
|
|
//CHECKING IF THE PORTLET URL CONTAINS THE VRE NAME INTO URL
|
|
if(PORTLET_URL_FOR_SCOPE.toLowerCase().contains(vreNameLower)){
|
|
//THE PORLTET URL READ FROM GENERIC RESOUCE 'CkanPortlet' SHOULD BE ALREADY VALID, POITING TO CKAN PORTLET
|
|
return PORTLET_URL_FOR_SCOPE;
|
|
}else{
|
|
//ADDING VRE getApiKeyFromUsernameNAME AND THE SUFFIX 'CATALOGUE_TAB_ENDING_URL' TO URL
|
|
String buildedUrl = PORTLET_URL_FOR_SCOPE.endsWith("/") ? PORTLET_URL_FOR_SCOPE : PORTLET_URL_FOR_SCOPE + "/";
|
|
String defaultSuffix = vreNameLower + CATALOGUE_TAB_ENDING_URL;
|
|
buildedUrl+= defaultSuffix;
|
|
LOG.warn("The Portlet URL read from Generic Resource 'Ckan-Porltet' does not contain the portlet suffix, so I added the default: "+defaultSuffix);
|
|
return buildedUrl;
|
|
}
|
|
}
|
|
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#findLicenseIdByLicenseTitle(java.lang.String)
|
|
*/
|
|
@Override
|
|
public String findLicenseIdByLicenseTitle(String chosenLicense) {
|
|
LOG.debug("Requested license id");
|
|
|
|
// checks
|
|
checkNotNull(chosenLicense);
|
|
|
|
//retrieve the list of available licenses
|
|
List<CkanLicense> licenses = ckanCaller.getLicenseList();
|
|
|
|
for (CkanLicense ckanLicense : licenses) {
|
|
if(ckanLicense.getTitle().equals(chosenLicense))
|
|
return ckanLicense.getId();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getLicenseTitles()
|
|
*/
|
|
@Override
|
|
public List<String> getLicenseTitles() {
|
|
|
|
LOG.debug("Request for CKAN licenses");
|
|
// get the url and the api key of the user
|
|
List<String> result = new ArrayList<String>();
|
|
// retrieve the list of available licenses
|
|
List<CkanLicense> licenses = ckanCaller.getLicenseList();
|
|
|
|
for (CkanLicense ckanLicense : licenses) {
|
|
|
|
result.add(ckanLicense.getTitle());
|
|
LOG.debug("License is " + ckanLicense.getTitle() + " and id " + ckanLicense.getId());
|
|
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getLicenses()
|
|
*/
|
|
@Override
|
|
public List<CkanLicense> getLicenses() {
|
|
LOG.debug("Request for CKAN licenses (original jackan objects are going to be retrieved)");
|
|
// retrieve the list of available licenses
|
|
return ckanCaller.getLicenseList();
|
|
}
|
|
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getDataset(java.lang.String, java.lang.String)
|
|
*/
|
|
@Override
|
|
public CkanDataset getDataset(String datasetIdOrName, String username) {
|
|
LOG.info("Called getDataset with id or name" + datasetIdOrName+ " and username: "+username);
|
|
|
|
// checks
|
|
checkNotNull(datasetIdOrName);
|
|
checkArgument(!datasetIdOrName.isEmpty());
|
|
|
|
try {
|
|
|
|
if (username != null && !username.isEmpty()) {
|
|
LOG.info("username found. Calling the " + ExtendCkanClient.class.getSimpleName());
|
|
String apiKey = getApiKeyFromUsername(username);
|
|
ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, apiKey);
|
|
return client.getDataset(datasetIdOrName);
|
|
}
|
|
|
|
// String authzToken = SecurityTokenProvider.instance.get();
|
|
// if (authzToken != null && !authzToken.isEmpty()) {
|
|
// LOG.info("gcube-token found. Calling the gCat client");
|
|
// String jsonDataset = gCatCaller.getDatasetForName(datasetId);
|
|
// return MarshUnmarshCkanObject.toCkanDataset(jsonDataset, METHOD.TO_READ);
|
|
// }
|
|
|
|
LOG.info("No username found. Calling Ckan Client without API-KEY");
|
|
return ckanCaller.getDataset(datasetIdOrName);
|
|
|
|
} catch (Exception e) {
|
|
LOG.error("Unable to retrieve such dataset, returning null ...", e);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getUnencryptedUrlFromDatasetIdOrName(java.lang.String)
|
|
*/
|
|
@Override
|
|
public String getUnencryptedUrlFromDatasetIdOrName(String datasetIdOrName) {
|
|
LOG.debug("Request coming for getting dataset url (not encrypted) of dataset with name/id " + datasetIdOrName);
|
|
|
|
// checks
|
|
checkNotNull(datasetIdOrName);
|
|
checkArgument(!datasetIdOrName.isEmpty());
|
|
String url = null;
|
|
|
|
try {
|
|
// get the dataset from name
|
|
ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, CKAN_TOKEN_SYS);
|
|
CkanDataset dataset = client.getDataset(datasetIdOrName);
|
|
String name = dataset.getName();
|
|
|
|
if (dataset != null) {
|
|
|
|
if (getUriResolverUrl() != null)
|
|
url = getUrlForProduct(CONTEXT, EntityContext.DATASET, name);
|
|
|
|
if (url == null || url.isEmpty())
|
|
url = getPortletUrl() + "?" + URLEncoder.encode("path=/dataset/" + name, "UTF-8");
|
|
|
|
}
|
|
} catch (Exception e) {
|
|
LOG.error("Error while retrieving dataset with id/name=" + datasetIdOrName, e);
|
|
} // requestEntity.put("clear_url", Boolean.toString(unencrypted));
|
|
return url;
|
|
}
|
|
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getUserRoleByGroup(java.lang.String)
|
|
*/
|
|
@Override
|
|
public Map<String, Map<CkanGroup, RolesCkanGroupOrOrg>> getUserRoleByGroup(String username) {
|
|
LOG.info("Get user role by group called. The username is: " + username);
|
|
|
|
checkNotNull(username);
|
|
|
|
Map<String, Map<CkanGroup, RolesCkanGroupOrOrg>> toReturn = new HashMap<String, Map<CkanGroup, RolesCkanGroupOrOrg>>();
|
|
|
|
try {
|
|
|
|
String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username);
|
|
Map<String, RolesCkanGroupOrOrg> partialResult = dbCaller.getGroupsByUserFromDB(ckanUsername);
|
|
|
|
for (String groupID : partialResult.keySet()) {
|
|
|
|
CkanGroup group = ckanCaller.getGroup(groupID);
|
|
HashMap<CkanGroup, RolesCkanGroupOrOrg> subMap = new HashMap<CkanGroup, RolesCkanGroupOrOrg>();
|
|
subMap.put(group, partialResult.get(groupID));
|
|
toReturn.put(groupID, subMap);
|
|
}
|
|
|
|
LOG.debug("Returning map " + toReturn);
|
|
LOG.info("Found " + toReturn.size() + " group/s with the user " + username);
|
|
} catch (Exception e) {
|
|
LOG.error("Failed to retrieve roles of user in his/her own groups", e);
|
|
}
|
|
|
|
return toReturn;
|
|
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getUserRoleByOrganization(java.lang.String)
|
|
*/
|
|
@Override
|
|
public Map<String, Map<CkanOrganization, RolesCkanGroupOrOrg>> getUserRoleByOrganization(String username) {
|
|
LOG.info("Get user role by organization called. The username is: " + username);
|
|
|
|
checkNotNull(username);
|
|
|
|
Map<String, Map<CkanOrganization, RolesCkanGroupOrOrg>> toReturn = new HashMap<String, Map<CkanOrganization, RolesCkanGroupOrOrg>>();
|
|
|
|
try {
|
|
|
|
String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username);
|
|
Map<String, RolesCkanGroupOrOrg> partialResult = dbCaller.getOrganizationsByUserFromDB(ckanUsername);
|
|
|
|
for (String orgID : partialResult.keySet()) {
|
|
|
|
CkanOrganization org = ckanCaller.getOrganization(orgID);
|
|
HashMap<CkanOrganization, RolesCkanGroupOrOrg> subMap = new HashMap<CkanOrganization, RolesCkanGroupOrOrg>();
|
|
subMap.put(org, partialResult.get(orgID));
|
|
toReturn.put(orgID, subMap);
|
|
LOG.debug("For organisation: " + org.getName() + ", the user " + username + " has role: " + subMap);
|
|
}
|
|
|
|
LOG.debug("Returning map " + toReturn);
|
|
LOG.info("Found " + toReturn.size() + " organization/s with the user " + username);
|
|
} catch (Exception e) {
|
|
LOG.error("Failed to retrieve roles of user in his/her own groups", e);
|
|
}
|
|
|
|
return toReturn;
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieve an url for the tuple scope, entity, entity name.
|
|
*
|
|
* @param context the context
|
|
* @param entityContext the entity context
|
|
* @param entityName the entity name
|
|
* @return the url for product
|
|
*/
|
|
private String getUrlForProduct(String context, EntityContext entityContext, String entityName) {
|
|
|
|
String toReturn = null;
|
|
|
|
try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
|
|
|
|
HttpPost httpPostRequest = new HttpPost(getUriResolverUrl());
|
|
|
|
JSONObject requestEntity = new JSONObject();
|
|
requestEntity.put("gcube_scope", context);
|
|
requestEntity.put("entity_context", entityContext.toString());
|
|
requestEntity.put("entity_name", entityName);
|
|
|
|
StringEntity params = new StringEntity(requestEntity.toJSONString(), ContentType.APPLICATION_JSON);
|
|
httpPostRequest.setEntity(params);
|
|
|
|
HttpResponse response = httpClient.execute(httpPostRequest);
|
|
|
|
if (response.getStatusLine().getStatusCode() != 200)
|
|
throw new Exception("There was an error while creating an url " + response.getStatusLine());
|
|
|
|
toReturn = EntityUtils.toString(response.getEntity());
|
|
LOG.debug("Result is " + toReturn);
|
|
|
|
} catch (Exception e) {
|
|
LOG.error("Failed to get an url for this product", e);
|
|
}
|
|
|
|
return toReturn;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getLandingPages()
|
|
*/
|
|
@Override
|
|
public LandingPages getLandingPages() throws Exception {
|
|
|
|
LandingPages landingPages = new LandingPages();
|
|
landingPages.setUrlGroups(PORTLET_URL_FOR_SCOPE + "?path=/group/");
|
|
landingPages.setUrlItems(PORTLET_URL_FOR_SCOPE + "?path=/dataset/");
|
|
landingPages.setUrlOrganizations(PORTLET_URL_FOR_SCOPE + "?path=/organization/");
|
|
landingPages.setUrlTypes(PORTLET_URL_FOR_SCOPE + "?path=/type/");
|
|
return landingPages;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getUriResolverUrl()
|
|
*/
|
|
@Override
|
|
public String getUriResolverUrl() {
|
|
return URI_RESOLVER_URL;
|
|
}
|
|
|
|
/**
|
|
* Check if the manage product is enabled.
|
|
*
|
|
* @return true, if is manage product enabled
|
|
*/
|
|
@Override
|
|
public boolean isManageProductEnabled() {
|
|
return MANAGE_PRODUCT_BUTTON;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getGroupByName(java.lang.String)
|
|
*/
|
|
@Override
|
|
public CkanGroup getGroupByName(String name) {
|
|
String ckanName = CatalogueUtilMethods.fromGroupTitleToName(name);
|
|
try{
|
|
return ckanCaller.getGroup(ckanName);
|
|
}catch(Exception e){
|
|
LOG.error("Failed to retrieve the group with name" + name, e);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#isNotificationToUsersEnabled()
|
|
*/
|
|
@Override
|
|
public boolean isNotificationToUsersEnabled() {
|
|
return ALERT_USERS_ON_POST_CREATION;
|
|
}
|
|
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getOrganizationsByUser(java.lang.String)
|
|
*/
|
|
@Override
|
|
public List<CkanOrganization> getOrganizationsByUser(String username) {
|
|
|
|
LOG.debug("Requested organizations for user " + username);
|
|
|
|
// checks
|
|
checkNotNull(username);
|
|
// in order to avoid errors, the username is always converted
|
|
String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username);
|
|
// list to return
|
|
List<CkanOrganization> toReturn = new ArrayList<CkanOrganization>();
|
|
|
|
try {
|
|
|
|
Map<String, RolesCkanGroupOrOrg> partialResult = dbCaller.getOrganizationsByUserFromDB(ckanUsername);
|
|
|
|
for (String orgID : partialResult.keySet()) {
|
|
CkanOrganization org = ckanCaller.getOrganization(orgID, false);
|
|
LOG.debug("User " + ckanUsername + " is into " + org.getName());
|
|
toReturn.add(org);
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
LOG.error("Unable to get user's organizations", e);
|
|
}
|
|
return toReturn;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getGroupsByUser(java.lang.String)
|
|
*/
|
|
@Override
|
|
public List<CkanGroup> getGroupsByUser(String username) {
|
|
LOG.debug("Requested groups for user " + username);
|
|
|
|
// checks
|
|
checkNotNull(username);
|
|
// in order to avoid errors, the username is always converted
|
|
String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username);
|
|
// list to return
|
|
List<CkanGroup> toReturn = new ArrayList<CkanGroup>();
|
|
|
|
try {
|
|
|
|
Map<String, RolesCkanGroupOrOrg> partialResult = dbCaller.getGroupsByUserFromDB(ckanUsername);
|
|
|
|
for (String groupID : partialResult.keySet()) {
|
|
CkanGroup group = ckanCaller.getGroup(groupID, false);
|
|
LOG.debug("User " + ckanUsername + " is into " + group.getName());
|
|
toReturn.add(group);
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
LOG.error("Unable to get user's groups", e);
|
|
}
|
|
return toReturn;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getOrganizationsIds()
|
|
*/
|
|
@Override
|
|
public List<String> getOrganizationsIds() {
|
|
|
|
List<String> toReturn = new ArrayList<String>();
|
|
List<CkanOrganization> orgs = ckanCaller.getOrganizationList();
|
|
|
|
for (CkanOrganization ckanOrganization : orgs) {
|
|
LOG.debug("Retrieved org " + ckanOrganization.getName());
|
|
toReturn.add(ckanOrganization.getId());
|
|
}
|
|
|
|
return toReturn;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getOrganizationsNames()
|
|
*/
|
|
@Override
|
|
public List<String> getOrganizationsNames() {
|
|
|
|
List<String> toReturn = new ArrayList<String>();
|
|
List<CkanOrganization> orgs = ckanCaller.getOrganizationList();
|
|
|
|
for (CkanOrganization ckanOrganization : orgs) {
|
|
LOG.debug("Retrieved org " + ckanOrganization.getName());
|
|
toReturn.add(ckanOrganization.getName());
|
|
}
|
|
|
|
return toReturn;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getOrganizationsNamesByUser(java.lang.String)
|
|
*/
|
|
@Override
|
|
public List<String> getOrganizationsNamesByUser(String username) {
|
|
|
|
LOG.debug("Requested organizations for user " + username);
|
|
|
|
// checks
|
|
checkNotNull(username);
|
|
|
|
// in order to avoid errors, the username is always converted
|
|
String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username);
|
|
List<CkanOrganization> orgs = getOrganizationsByUser(ckanUsername);
|
|
List<String> orgsName = new ArrayList<String>();
|
|
|
|
for (CkanOrganization ckanOrganization : orgs) {
|
|
orgsName.add(ckanOrganization.getName());
|
|
LOG.debug("Organization name is " + ckanOrganization.getName());
|
|
}
|
|
|
|
return orgsName;
|
|
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getRoleOfUserInOrganization(java.lang.String, java.lang.String)
|
|
*/
|
|
@Override
|
|
public String getRoleOfUserInOrganization(String username, String orgName) {
|
|
|
|
String toReturn = null;
|
|
|
|
String apiKey = getApiKeyFromUsername(username);
|
|
String usernameCkan = CatalogueUtilMethods.fromUsernameToCKanUsername(username);
|
|
|
|
try {
|
|
|
|
ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, apiKey);
|
|
List<CkanUser> users = client.getOrganization(orgName).getUsers();
|
|
for (CkanUser ckanUser : users) {
|
|
if (ckanUser.getName().equals(usernameCkan)) {
|
|
toReturn = ckanUser.getCapacity();
|
|
break;
|
|
}
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
LOG.error("Unable to retrieve the role the user has into organization: " + orgName, e);
|
|
}
|
|
|
|
return toReturn;
|
|
}
|
|
|
|
|
|
/**
|
|
* Check if the user is valid by checking if its API_KEY is present into DB.
|
|
*
|
|
* @param username the username
|
|
* @return true, if successful
|
|
*/
|
|
@Override
|
|
public boolean checkValidUser(String username) {
|
|
|
|
String apiKey = getApiKeyFromUsername(username);
|
|
return apiKey != null;
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets the api key from username.
|
|
*
|
|
* @param username the username
|
|
* @return the api key from username
|
|
*/
|
|
private String getApiKeyFromUsername(String username) {
|
|
|
|
LOG.debug("Request api key for user = " + username);
|
|
|
|
// checks
|
|
checkNotNull(username);
|
|
checkArgument(!username.isEmpty());
|
|
|
|
// in order to avoid errors, the username is always converted
|
|
String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username);
|
|
|
|
// check in the hashmap first
|
|
if (apiKeysMap.containsKey(ckanUsername)) {
|
|
CKANTokenBean bean = apiKeysMap.get(ckanUsername);
|
|
if (bean.timestamp + EXPIRE_KEY_TIME > System.currentTimeMillis()) { // it's still ok
|
|
return bean.apiKey;
|
|
}
|
|
}
|
|
|
|
LOG.debug("Api key was not in cache or it expired");
|
|
|
|
try {
|
|
|
|
String apiToReturn = dbCaller.getApiKeyFromUsername(username, State.ACTIVE.name().toLowerCase());
|
|
|
|
// save into the hashmap
|
|
if (apiToReturn != null)
|
|
apiKeysMap.put(ckanUsername, new CKANTokenBean(apiToReturn, System.currentTimeMillis()));
|
|
|
|
return apiToReturn;
|
|
|
|
} catch (Exception e) {
|
|
LOG.error("Unable to retrieve key for user " + ckanUsername, e);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#existProductWithNameOrId(java.lang.String)
|
|
*/
|
|
@Override
|
|
public boolean existProductWithNameOrId(String nameOrId) {
|
|
|
|
checkNotNull(nameOrId);
|
|
checkArgument(!nameOrId.isEmpty());
|
|
|
|
try {
|
|
ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, CKAN_TOKEN_SYS);
|
|
CkanDataset product = client.getDataset(nameOrId);
|
|
return product != null;
|
|
} catch (Exception e) {
|
|
LOG.debug("A dataset with name " + nameOrId + " doesn't exist");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getOrganizationByIdOrName(java.lang.String)
|
|
*/
|
|
@Override
|
|
public CkanOrganization getOrganizationByIdOrName(String idOrName) {
|
|
|
|
checkNotNull(idOrName);
|
|
|
|
String ckanName = idOrName.toLowerCase();
|
|
try {
|
|
|
|
return ckanCaller.getOrganization(ckanName);
|
|
|
|
} catch (Exception e) {
|
|
LOG.warn("Failed to retrieve the organization with name " + idOrName + " on the ckan: "
|
|
+ ckanCaller.getCatalogUrl(), e);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Check if the user has this role into the organization/group with
|
|
* groupOrOrganization name.
|
|
*
|
|
* @param ckanUsername the ckan username
|
|
* @param groupOrOrganization the group or organization
|
|
* @param correspondentRoleToCheck the correspondent role to check
|
|
* @param group the group
|
|
* @return true if he has the role, false otherwise
|
|
* @throws Exception the exception
|
|
*/
|
|
protected boolean isRoleAlreadySet(String ckanUsername, String groupOrOrganization,
|
|
RolesCkanGroupOrOrg correspondentRoleToCheck, boolean group) throws Exception {
|
|
|
|
// get the users (if you try ckanOrganization.getUsers() it returns null.. maybe
|
|
// a bug TODO)
|
|
List<CkanUser> users;
|
|
|
|
if (group)
|
|
users = ckanCaller.getGroup(groupOrOrganization).getUsers();
|
|
else
|
|
users = ckanCaller.getOrganization(groupOrOrganization).getUsers();
|
|
|
|
for (CkanUser ckanUser : users) {
|
|
if (ckanUser.getName().equals(ckanUsername))
|
|
if (ckanUser.getCapacity().equals(RolesCkanGroupOrOrg.convertToCkanCapacity(correspondentRoleToCheck)))
|
|
return true;
|
|
else
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Just check if the group exists.
|
|
*
|
|
* @param nameOrId the name or id
|
|
* @return the ckan group
|
|
*/
|
|
private CkanGroup groupExists(String nameOrId) {
|
|
|
|
CkanGroup toReturn = null;
|
|
|
|
try {
|
|
ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, CKAN_TOKEN_SYS);
|
|
toReturn = client.getGroup(nameOrId);
|
|
|
|
} catch (JackanException je) {
|
|
LOG.error("The group " + nameOrId + " doesn't exist");
|
|
}
|
|
|
|
return toReturn;
|
|
}
|
|
|
|
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getParentGroups(java.lang.String, java.lang.String)
|
|
*/
|
|
@Override
|
|
public List<CkanGroup> getParentGroups(String groupName, String apiKey) {
|
|
// checks
|
|
checkNotNull(groupName);
|
|
checkNotNull(apiKey);
|
|
|
|
try{
|
|
ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, apiKey);
|
|
return client.getGroup(groupName).getGroups();
|
|
}catch(Exception e){
|
|
LOG.error("Something went wrong, returning null", e);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getOrganizationByName(java.lang.String)
|
|
*/
|
|
@Override
|
|
public CkanOrganization getOrganizationByName(String name) {
|
|
|
|
checkNotNull(name);
|
|
|
|
String ckanName = name.toLowerCase();
|
|
try{
|
|
|
|
return ckanCaller.getOrganization(ckanName);
|
|
|
|
}catch(Exception e){
|
|
LOG.warn("Failed to retrieve the organization with name " +name+ " on the ckan: "+ckanCaller.getCatalogUrl(), e);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* *****************************************************************************
|
|
*
|
|
*
|
|
* WRITE OPERATIONS
|
|
*
|
|
*
|
|
* *****************************************************************************.
|
|
*
|
|
* @param username the username
|
|
* @param organizationName the organization name
|
|
* @param correspondentRoleToCheck the correspondent role to check
|
|
* @return true, if successful
|
|
*/
|
|
|
|
|
|
@Override
|
|
public boolean checkRoleIntoOrganization(String username, String organizationName,
|
|
RolesCkanGroupOrOrg correspondentRoleToCheck) {
|
|
|
|
LOG.debug("Request for checking if " + username + " into organization " + organizationName + " has role " + correspondentRoleToCheck);
|
|
|
|
// checks
|
|
checkNotNull(username);
|
|
checkNotNull(organizationName);
|
|
checkNotNull(correspondentRoleToCheck);
|
|
checkArgument(!username.isEmpty());
|
|
checkArgument(!organizationName.isEmpty());
|
|
|
|
// convert ckan username
|
|
String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username);
|
|
|
|
// check if this role is already present in ckan for this user within the organization
|
|
String organizationNameToCheck = organizationName.toLowerCase();
|
|
|
|
try{
|
|
boolean alreadyPresent = isRoleAlreadySet(ckanUsername, organizationNameToCheck, correspondentRoleToCheck, false);
|
|
|
|
if(alreadyPresent)
|
|
return true; // just return
|
|
else{
|
|
|
|
//TODO PASS by GCAT?
|
|
// we need to use the APIs to make it
|
|
String path = "/api/3/action/organization_member_create";
|
|
|
|
JSONObject obj = new JSONObject();
|
|
obj.put("id", organizationNameToCheck);
|
|
obj.put("username", ckanUsername);
|
|
obj.put("role", RolesCkanGroupOrOrg.convertToCkanCapacity(correspondentRoleToCheck));
|
|
|
|
LOG.debug("API request for organization membership is going to be " + obj.toJSONString());
|
|
|
|
|
|
try(CloseableHttpClient httpClient = HttpClientBuilder.create().build();) {
|
|
HttpPost request = new HttpPost(CKAN_CATALOGUE_URL + path);
|
|
request.addHeader("Authorization", CKAN_TOKEN_SYS); // sys token
|
|
StringEntity params = new StringEntity(obj.toJSONString());
|
|
request.setEntity(params);
|
|
HttpResponse response = httpClient.execute(request);
|
|
LOG.debug("Response code is " + response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase());
|
|
|
|
return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
|
|
|
|
}catch (Exception ex) {
|
|
LOG.error("Error while trying to change the role for this user ", ex);
|
|
}
|
|
}
|
|
}catch (Exception ex) {
|
|
LOG.error("Unable to check if this role was already set, please check your parameters! ", ex);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#checkRoleIntoGroup(java.lang.String, java.lang.String, org.gcube.datacatalogue.utillibrary.shared.RolesCkanGroupOrOrg)
|
|
*/
|
|
@Override
|
|
public boolean checkRoleIntoGroup(String username, String groupName, RolesCkanGroupOrOrg correspondentRoleToCheck) {
|
|
LOG.debug("Request for checking if " + username + " into group " + groupName + " has role " + correspondentRoleToCheck);
|
|
|
|
// checks
|
|
checkNotNull(username);
|
|
checkNotNull(groupName);
|
|
checkNotNull(correspondentRoleToCheck);
|
|
checkArgument(!username.isEmpty());
|
|
checkArgument(!groupName.isEmpty());
|
|
|
|
// convert ckan username
|
|
String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username);
|
|
|
|
// check if this role is already present in ckan for this user within the group
|
|
String groupNameToCheck = CatalogueUtilMethods.fromGroupTitleToName(groupName);
|
|
|
|
try{
|
|
boolean alreadyPresent = isRoleAlreadySet(ckanUsername, groupNameToCheck, correspondentRoleToCheck, true);
|
|
|
|
if(alreadyPresent)
|
|
return true; // just return
|
|
else{
|
|
|
|
// we need to use the apis to make it
|
|
String path = "/api/3/action/group_member_create";
|
|
|
|
JSONObject obj = new JSONObject();
|
|
obj.put("id", groupNameToCheck);
|
|
obj.put("username", ckanUsername);
|
|
obj.put("role", RolesCkanGroupOrOrg.convertToCkanCapacity(correspondentRoleToCheck));
|
|
|
|
LOG.debug("API request for organization membership is going to be " + obj.toJSONString());
|
|
|
|
try(CloseableHttpClient httpClient = HttpClientBuilder.create().build();) {
|
|
HttpPost request = new HttpPost(CKAN_CATALOGUE_URL + path);
|
|
request.addHeader("Authorization", CKAN_TOKEN_SYS); // sys token
|
|
StringEntity params = new StringEntity(obj.toJSONString());
|
|
request.setEntity(params);
|
|
HttpResponse response = httpClient.execute(request);
|
|
LOG.debug("Response code is " + response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase());
|
|
|
|
return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
|
|
|
|
}catch (Exception ex) {
|
|
LOG.error("Error while trying to change the role for this user ", ex);
|
|
}
|
|
}
|
|
}catch (Exception ex) {
|
|
LOG.error("Unable to check if this role was already set, please check your parameters! ", ex);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#createCkanDatasetMultipleCustomFields(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, long, java.lang.String, java.lang.String, java.util.List, java.util.Map, java.util.List, boolean, boolean, boolean)
|
|
*/
|
|
@Override
|
|
public String createCkanDatasetMultipleCustomFields(String username, String title, String name, String organizationName,
|
|
String author, String authorMail, String maintainer, String maintainerMail, long version,
|
|
String description, String licenseId, List<String> tags, Map<String, List<String>> customFieldsMultiple,
|
|
List<ResourceBean> resources, boolean setPublic, boolean setSearchable, boolean socialPost) throws Exception {
|
|
LOG.info("Called createCkanDatasetMultipleCustomFields");
|
|
|
|
// checks (minimum)
|
|
checkNotNull(username);
|
|
//checkNotNull(organizationNameOrId);
|
|
//checkArgument(!organizationNameOrId.isEmpty());
|
|
checkArgument(!(title == null && name == null || title.isEmpty() && name.isEmpty()), "Name and Title cannot be empty/null at the same time!");
|
|
|
|
GcubeContext gcubeContext = null;
|
|
try {
|
|
|
|
gcubeContext = GCubeUtils.detectTheOrgNameContexts(organizationName, username, true);
|
|
|
|
String toPassOrganizationToGcat = null; //Not needed to pass this information to gCat, never.
|
|
// String ckanUsername = getUserFromApiKey(apiKey).getName();
|
|
CkanDataset dataset = CKANConveter.toCkanDataset(ckanCaller, username, title, name, toPassOrganizationToGcat, author, authorMail,
|
|
maintainer, maintainerMail, version, description, licenseId, tags, null, customFieldsMultiple,
|
|
resources, setPublic, setSearchable);
|
|
|
|
// trying to create by gCat
|
|
String jsonValueDataset = MarshUnmarshCkanObject.toJsonValueDataset(dataset,METHOD.TO_CREATE);
|
|
LOG.info("Serialized dataset is: " + jsonValueDataset);
|
|
/*JSONObject jsonDataset = null;
|
|
try {
|
|
JSONParser parser = new JSONParser();
|
|
jsonDataset = (JSONObject) parser.parse(jsonValueDataset);
|
|
|
|
// Object jsonSpatial = jsonDataset.get("spatial");
|
|
// if (jsonSpatial != null) {
|
|
// ObjectMapper objectMapper = new ObjectMapper();
|
|
// objectMapper.configure(Feature.QUOTE_FIELD_NAMES, false);
|
|
// String spatialUnquoted = objectMapper.writeValueAsString(jsonSpatial);
|
|
// System.out.println(spatialUnquoted);
|
|
// jsonDataset.put("spatial", spatialUnquoted);
|
|
// }
|
|
|
|
}catch (Exception e) {
|
|
LOG.error("Serialized dataset not parsable as JSON: ", e);
|
|
throw new Exception("Error on reading data, refresh and try again");
|
|
}
|
|
|
|
if(jsonDataset==null)
|
|
throw new Exception("Error on converting data");*/
|
|
|
|
jsonValueDataset = gCatCaller.createDataset(jsonValueDataset,socialPost);
|
|
LOG.debug("Created dataset is: " + jsonValueDataset);
|
|
|
|
if(jsonValueDataset != null){
|
|
CkanDataset toCkanDataset = MarshUnmarshCkanObject.toCkanDataset(jsonValueDataset,METHOD.TO_READ);
|
|
LOG.info("Dataset with name " + toCkanDataset.getName() + " has been created correctly");
|
|
return toCkanDataset.getId();
|
|
}
|
|
}catch (Exception e) {
|
|
LOG.error("Error on creating the dataset: ", e);
|
|
throw e;
|
|
}finally {
|
|
|
|
if(gcubeContext!=null)
|
|
GCubeUtils.revertToSourceContext(gcubeContext);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#patchFieldsForDataset(java.lang.String, java.util.Map)
|
|
*/
|
|
@Override
|
|
public boolean patchFieldsForDataset(String datasetIdOrName, Map<String, String> mapFields) throws Exception {
|
|
LOG.info("Called patchFieldsForDataset " + mapFields + " for dataset id/name: " + datasetIdOrName);
|
|
|
|
checkNotNull(datasetIdOrName);
|
|
checkNotNull(mapFields);
|
|
|
|
try {
|
|
|
|
CkanDataset dataset = ckanCaller.getDataset(datasetIdOrName);
|
|
String datasetId = dataset.getId();
|
|
|
|
JSONObject jsonObj = new JSONObject();
|
|
for (String key : mapFields.keySet()) {
|
|
jsonObj.put(key, mapFields.get(key));
|
|
}
|
|
|
|
jsonObj.put("id", datasetId);
|
|
|
|
LOG.debug("Json Dataset is: " + jsonObj);
|
|
gCatCaller.patchDataset(dataset.getName(), jsonObj);
|
|
LOG.info("Patch operation for dataset " + datasetId + " terminates without errors");
|
|
return true;
|
|
} catch (Exception e) {
|
|
LOG.error("Error occurred trying to patch the dataset with id: " + datasetIdOrName, e);
|
|
throw new Exception("Unable to patch the dataset. Error: " + e.getMessage());
|
|
}
|
|
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#setSearchableFieldForDataset(java.lang.String, boolean)
|
|
*/
|
|
@Override
|
|
public boolean setSearchableFieldForDataset(String datasetId, boolean searchable) throws Exception {
|
|
LOG.info("Set searchalbe field as " + searchable + " for dataset id: " + datasetId);
|
|
|
|
checkNotNull(datasetId);
|
|
|
|
try {
|
|
String searchableAsString = searchable ? "True" : "False";
|
|
JSONObject jsonObj = new JSONObject();
|
|
jsonObj.put("id", datasetId); // just to be sure
|
|
jsonObj.put("searchable", searchableAsString);
|
|
LOG.debug("Json Dataset is: " + jsonObj);
|
|
gCatCaller.patchDataset(datasetId, jsonObj);
|
|
LOG.info("Set 'searchable' field for dataset " + datasetId + " terminates without errors");
|
|
return true;
|
|
} catch (Exception e) {
|
|
LOG.error("Error occured trying to set the 'searchable' field for the dataset with id: " + datasetId,
|
|
e.getMessage());
|
|
throw new Exception("Unable to set the 'searchable' field for this dataset. Error: " + e.getMessage());
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#addResourceToDataset(org.gcube.datacatalogue.utillibrary.shared.ResourceBean)
|
|
*/
|
|
@Override
|
|
public String addResourceToDataset(ResourceBean resourceBean, String organizationName, String username) throws Exception {
|
|
LOG.info("Called addResourceToDataset by this bean " + resourceBean);
|
|
|
|
// checks
|
|
checkNotNull(resourceBean);
|
|
checkNotNull(resourceBean.getUrl());
|
|
|
|
//Commented since #21259
|
|
/*boolean isAccessibleURL = false;
|
|
try {
|
|
isAccessibleURL = CatalogueUtilMethods.resourceExists(resourceBean.getUrl());
|
|
} catch (Exception e) {
|
|
throw new Exception("It seems the resource at this url " + resourceBean.getUrl()+" is not reachable. Error: "+e.getMessage());
|
|
}
|
|
|
|
if(!isAccessibleURL){
|
|
throw new Exception("It seems there is no resource at this url " + resourceBean.getUrl());
|
|
}*/
|
|
|
|
GcubeContext gcubeContext = null;
|
|
try {
|
|
|
|
//Switch the context if needed
|
|
gcubeContext = GCubeUtils.detectTheOrgNameContexts(organizationName, username, true);
|
|
|
|
CkanResource resource = CKANConveter.toCkanResource(CKAN_CATALOGUE_URL, resourceBean);
|
|
|
|
String jsonValueResource = MarshUnmarshCkanObject.toJsonValueResource(resource, METHOD.TO_CREATE);
|
|
LOG.debug("Serialized resource is: " + jsonValueResource);
|
|
jsonValueResource = gCatCaller.addResourceToDataset(resourceBean.getDatasetId(), jsonValueResource);
|
|
LOG.debug("Added resource to dataset is: " + jsonValueResource);
|
|
|
|
CkanResource createdRes = MarshUnmarshCkanObject.toCkanResource(jsonValueResource);
|
|
|
|
if (createdRes != null) {
|
|
LOG.info("Resource with id: " + createdRes.getId() + ", name: "+createdRes.getName()+" added correclty");
|
|
return createdRes.getId();
|
|
}
|
|
}catch (Exception e) {
|
|
LOG.error("Unable to add the resource "+resourceBean, e);
|
|
}finally {
|
|
//revert the context if needed
|
|
if(gcubeContext!=null)
|
|
GCubeUtils.revertToSourceContext(gcubeContext);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#deleteResourceFromDataset(java.lang.String)
|
|
*/
|
|
@Override
|
|
public boolean deleteResourceFromDataset(String resourceId, String username) throws Exception {
|
|
LOG.info("Called deleteResourceFromDataset - resource with id " + resourceId);
|
|
|
|
// checks
|
|
checkNotNull(resourceId);
|
|
checkArgument(!resourceId.isEmpty());
|
|
|
|
GcubeContext gcubeContext = null;
|
|
try{
|
|
CkanResource theResource = ckanCaller.getResource(resourceId);
|
|
|
|
CkanDataset theDataset = getDataset(theResource.getPackageId(), username);
|
|
|
|
//Switch the context if needed
|
|
gcubeContext = GCubeUtils.detectTheOrgNameContexts(theDataset.getOrganization().getName(), username, true);
|
|
|
|
gCatCaller.deleteResource(theResource.getPackageId(), resourceId);
|
|
LOG.info("Resource with id: " + resourceId + " deleted correclty");
|
|
return true;
|
|
|
|
}catch(Exception e){
|
|
LOG.error("Unable to delete resource whose id is " + resourceId, e);
|
|
}finally {
|
|
//revert the context if needed
|
|
if(gcubeContext!=null)
|
|
GCubeUtils.revertToSourceContext(gcubeContext);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#createGroup(java.lang.String, java.lang.String, java.lang.String)
|
|
*/
|
|
@Override
|
|
public CkanGroup createGroup(String name, String title, String description) throws Exception {
|
|
|
|
// checks
|
|
checkNotNull(name);
|
|
checkArgument(!name.trim().isEmpty());
|
|
|
|
// check if it exists
|
|
CkanGroup toCreate = null;
|
|
LOG.debug("Request for creating group with name " + name + " title " + title + " and description " + description);
|
|
String normalizedName = CatalogueUtilMethods.fromGroupTitleToName(name);
|
|
if((toCreate = groupExists(name))!= null)
|
|
return toCreate;
|
|
else{
|
|
try{
|
|
|
|
CkanGroup group = new CkanGroup(normalizedName);
|
|
group.setTitle(title);
|
|
group.setDisplayName(title);
|
|
group.setDescription(description);
|
|
String jsonValueGroup = MarshUnmarshCkanObject.toJsonValueGroup(group);
|
|
LOG.trace("Serialized group is: " + jsonValueGroup);
|
|
|
|
String theGroup = gCatCaller.createGroup(jsonValueGroup);
|
|
toCreate = MarshUnmarshCkanObject.toCkanGroup(theGroup);
|
|
LOG.info("Created the group with id: " + toCreate.getId() + ", name: "+toCreate.getName());
|
|
|
|
}catch(JackanException je){
|
|
LOG.error("Unable to create such group", je);
|
|
}
|
|
}
|
|
|
|
return toCreate;
|
|
}
|
|
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#getRolesAndUsersGroup(java.lang.String)
|
|
*/
|
|
@Override
|
|
public Map<RolesCkanGroupOrOrg, List<String>> getRolesAndUsersGroup(String groupName) {
|
|
|
|
// checks
|
|
checkNotNull(groupName);
|
|
checkArgument(!groupName.isEmpty());
|
|
Map<RolesCkanGroupOrOrg, List<String>> capacityAndUsers = null;
|
|
String groupNameToCheck = CatalogueUtilMethods.fromGroupTitleToName(groupName);
|
|
|
|
CkanGroup group = ckanCaller.getGroup(groupNameToCheck);
|
|
|
|
if(group != null){
|
|
capacityAndUsers = new HashMap<RolesCkanGroupOrOrg, List<String>>();
|
|
List<CkanUser> users = group.getUsers();
|
|
for (CkanUser ckanUser : users) {
|
|
List<String> listUsers;
|
|
if(capacityAndUsers.containsKey(RolesCkanGroupOrOrg.convertFromCapacity(ckanUser.getCapacity()))){
|
|
listUsers = capacityAndUsers.get(RolesCkanGroupOrOrg.convertFromCapacity(ckanUser.getCapacity()));
|
|
}else
|
|
listUsers = new ArrayList<String>();
|
|
|
|
listUsers.add(ckanUser.getName());
|
|
capacityAndUsers.put(RolesCkanGroupOrOrg.convertFromCapacity(ckanUser.getCapacity()), listUsers);
|
|
|
|
}
|
|
|
|
LOG.info("Returning " + capacityAndUsers);
|
|
}
|
|
return capacityAndUsers;
|
|
}
|
|
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#assignDatasetToGroup(java.lang.String, java.lang.String)
|
|
*/
|
|
//TODO HAS TO BE REVISITED by gCAT
|
|
@Override
|
|
public boolean assignDatasetToGroup(String groupNameOrId, String datasetNameOrId) {
|
|
return assignDatasetToGroupBody(groupNameOrId, datasetNameOrId, false);
|
|
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see org.gcube.datacatalogue.utillibrary.server.DataCatalogue#patchProductCustomFields(java.lang.String, java.lang.String, java.util.Map, boolean)
|
|
*/
|
|
//TODO HAS TO BE REVISITED by gCAT
|
|
@Override
|
|
public boolean patchProductCustomFields(String productId, String username,
|
|
Map<String, List<String>> customFieldsToChange, boolean removeOld) {
|
|
|
|
// checks
|
|
checkNotNull(productId);
|
|
checkNotNull(username);
|
|
|
|
if(customFieldsToChange == null || customFieldsToChange.isEmpty()) // TODO.. remove all custom fields maybe?!
|
|
return true;
|
|
|
|
String apiKey = getApiKeyFromUsername(username);
|
|
|
|
LOG.info("Going to change product with id " + productId +"."
|
|
+ " Request comes from user with key " + apiKey.substring(0, 5) + "****************");
|
|
|
|
LOG.info("The new values are " + customFieldsToChange);
|
|
|
|
// Get already available custom fields
|
|
Map<String, List<String>> fromCKANCustomFields = new HashMap<String, List<String>>();
|
|
|
|
|
|
ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, apiKey);
|
|
List<CkanPair> extras = client.getDataset(productId).getExtras();
|
|
|
|
if(extras == null)
|
|
extras = new ArrayList<CkanPair>();
|
|
|
|
// fill the above map with these values
|
|
for (CkanPair ckanPair : extras) {
|
|
List<String> forThisValue = null;
|
|
String key = ckanPair.getKey();
|
|
if(fromCKANCustomFields.containsKey(key))
|
|
forThisValue = fromCKANCustomFields.get(key);
|
|
else
|
|
forThisValue = new ArrayList<String>();
|
|
forThisValue.add(ckanPair.getValue());
|
|
fromCKANCustomFields.put(key, forThisValue);
|
|
}
|
|
|
|
LOG.info("The generated map from jackan looks like " + fromCKANCustomFields + ". Going to merge them");
|
|
|
|
// merge them with the new values
|
|
Iterator<Entry<String, List<String>>> iteratorUserMap = customFieldsToChange.entrySet().iterator();
|
|
while (iteratorUserMap.hasNext()) {
|
|
Map.Entry<java.lang.String, java.util.List<java.lang.String>> entry = iteratorUserMap
|
|
.next();
|
|
|
|
String key = entry.getKey();
|
|
List<String> newValues = entry.getValue();
|
|
|
|
// get the unique set of values
|
|
Set<String> uniqueValues = new HashSet<String>();
|
|
|
|
if(fromCKANCustomFields.containsKey(key))
|
|
if(!removeOld)
|
|
uniqueValues.addAll(fromCKANCustomFields.get(key));
|
|
|
|
uniqueValues.addAll(newValues);
|
|
fromCKANCustomFields.put(key, new ArrayList<String>(uniqueValues));
|
|
}
|
|
|
|
LOG.info("After merging it is " + fromCKANCustomFields);
|
|
|
|
try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
|
|
String apiRequestUrl = CKAN_CATALOGUE_URL + "/api/3/action/package_patch";
|
|
HttpPost httpPostRequest = new HttpPost(apiRequestUrl);
|
|
httpPostRequest.setHeader("Authorization", apiKey);
|
|
|
|
// Request parameters to be replaced
|
|
JSONObject jsonRequest = new JSONObject();
|
|
|
|
// build the json array for the "extras" field.. each object looks like {"key": ..., "value": ...}
|
|
JSONArray extrasObject = new JSONArray();
|
|
|
|
Iterator<Entry<String, List<String>>> iteratorNewFields = fromCKANCustomFields.entrySet().iterator();
|
|
while (iteratorNewFields.hasNext()) {
|
|
Map.Entry<java.lang.String, java.util.List<java.lang.String>> entry = iteratorNewFields
|
|
.next();
|
|
|
|
String key = entry.getKey();
|
|
List<String> values = entry.getValue();
|
|
|
|
for (String value : values) {
|
|
JSONObject obj = new JSONObject();
|
|
obj.put("value", value);
|
|
obj.put("key", key);
|
|
extrasObject.add(obj);
|
|
}
|
|
}
|
|
|
|
// perform the request
|
|
jsonRequest.put("id", productId);
|
|
jsonRequest.put("extras", extrasObject);
|
|
|
|
LOG.debug("Request param is going to be " + jsonRequest);
|
|
|
|
StringEntity params = new StringEntity(jsonRequest.toJSONString(), ContentType.APPLICATION_JSON);
|
|
httpPostRequest.setEntity(params);
|
|
|
|
HttpResponse response = httpClient.execute(httpPostRequest);
|
|
|
|
if (response.getStatusLine().getStatusCode() < 200 || response.getStatusLine().getStatusCode() >= 300) {
|
|
throw new RuntimeException("failed to patch the product. response status line from "
|
|
+ apiRequestUrl + " was: " + response.getStatusLine());
|
|
}
|
|
|
|
return true;
|
|
|
|
}catch(Exception e){
|
|
LOG.error("Failed to patch the product ", e);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* The real body of the assignDatasetToGroup.
|
|
*
|
|
* @param groupNameOrId the group name or id
|
|
* @param datasetNameOrId the dataset name or id
|
|
* @param addOnParents the add on parents
|
|
* @return true, if successful
|
|
*/
|
|
private boolean assignDatasetToGroupBody(String groupNameOrId, String datasetNameOrId, boolean addOnParents) {
|
|
|
|
// checks
|
|
checkNotNull(groupNameOrId);
|
|
checkArgument(!groupNameOrId.isEmpty());
|
|
checkNotNull(datasetNameOrId);
|
|
checkArgument(!datasetNameOrId.isEmpty());
|
|
|
|
String groupNameToCheck = CatalogueUtilMethods.fromGroupTitleToName(groupNameOrId);
|
|
|
|
try(CloseableHttpClient httpClient = HttpClientBuilder.create().build();){
|
|
|
|
ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, CKAN_TOKEN_SYS);
|
|
|
|
// check the group exists
|
|
CkanGroup group = client.getGroup(groupNameToCheck);
|
|
|
|
// move to a list
|
|
List<String> groupNames = new ArrayList<String>();
|
|
groupNames.add(group.getName());
|
|
if(group != null && addOnParents){
|
|
findHierarchyGroups(groupNames, CKAN_TOKEN_SYS);
|
|
}
|
|
|
|
// we need to use the apis to make it
|
|
String pathPackageShow = CKAN_CATALOGUE_URL + "/api/3/action/package_show?id=" + datasetNameOrId;
|
|
HttpGet getRequest = new HttpGet(pathPackageShow);
|
|
getRequest.addHeader("Authorization", CKAN_TOKEN_SYS);
|
|
HttpResponse response = httpClient.execute(getRequest);
|
|
|
|
LOG.debug("Response is " + response.getStatusLine().getStatusCode() + " and message is " + response.getStatusLine().getReasonPhrase());
|
|
|
|
// read the json dataset and fetch the groups and fetch the groups' names, if any
|
|
if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
|
|
|
|
// parse the json and convert to java beans
|
|
String jsonAsString = EntityUtils.toString(response.getEntity());
|
|
JSONParser parser = new JSONParser();
|
|
JSONObject json = (JSONObject) parser.parse(jsonAsString);
|
|
JSONObject resultJson = (JSONObject) json.get("result");
|
|
JSONArray groupsJson = (JSONArray)resultJson.get("groups");
|
|
Iterator<JSONObject> it = groupsJson.iterator();
|
|
|
|
while (it.hasNext()) {
|
|
JSONObject object = it.next();
|
|
try{
|
|
if(object.containsKey("name"))
|
|
groupNames.add((String)object.get("name"));
|
|
}catch(Exception e){
|
|
LOG.error("Error", e);
|
|
}
|
|
}
|
|
|
|
// remove duplicates
|
|
Set<String> groupNamesSet = new HashSet<String>(groupNames);
|
|
|
|
LOG.debug("Groups to be added are " + groupNamesSet);
|
|
|
|
// now we patch the dataset with the new group
|
|
String pathUpdatePatch = CKAN_CATALOGUE_URL + "/api/3/action/package_patch";
|
|
|
|
JSONObject req = new JSONObject();
|
|
req.put("id", datasetNameOrId);
|
|
|
|
JSONArray groups = new JSONArray();
|
|
Iterator<String> iteratorNameSet = groupNamesSet.iterator();
|
|
while (iteratorNameSet.hasNext()) {
|
|
String groupName = iteratorNameSet.next();
|
|
JSONObject groupJSON = new JSONObject();
|
|
groupJSON.put("name", groupName);
|
|
groups.add(groupJSON);
|
|
}
|
|
req.put("groups", groups);
|
|
|
|
LOG.debug("Request for patch is going to be " + req.toJSONString());
|
|
|
|
HttpPost request = new HttpPost(pathUpdatePatch);
|
|
request.addHeader("Authorization", CKAN_TOKEN_SYS);
|
|
StringEntity params = new StringEntity(req.toJSONString());
|
|
request.setEntity(params);
|
|
HttpResponse responsePatch = httpClient.execute(request);
|
|
LOG.debug("Response code is " + responsePatch.getStatusLine().getStatusCode() + " and response message is " + responsePatch.getStatusLine().getReasonPhrase());
|
|
|
|
if(responsePatch.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
|
|
LOG.info("Dataset Added to the group!!");
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
}catch(Exception e){
|
|
LOG.error("Unable to make this association", e);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Find the hierarchy of trees.
|
|
*
|
|
* @param groupsTitles the groups titles
|
|
* @param apiKey the api key
|
|
*/
|
|
private void findHierarchyGroups(
|
|
List<String> groupsTitles,
|
|
String apiKey) {
|
|
ListIterator<String> iterator = groupsTitles.listIterator();
|
|
while (iterator.hasNext()) {
|
|
String group = iterator.next();
|
|
|
|
List<CkanGroup> parents = getParentGroups(group, apiKey);
|
|
|
|
if(parents == null || parents.isEmpty())
|
|
return;
|
|
|
|
for (CkanGroup ckanGroup : parents) {
|
|
List<String> parentsList = new ArrayList<String>(Arrays.asList(ckanGroup.getName()));
|
|
findHierarchyGroups(parentsList, apiKey);
|
|
for (String parent : parentsList) {
|
|
iterator.add(parent);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* *****************************************************************************
|
|
*
|
|
*
|
|
* MANAGEMENT OPERATIONS
|
|
*
|
|
*
|
|
* *****************************************************************************.
|
|
*
|
|
* @param username the username
|
|
* @param sourceOrganization the source organization
|
|
* @param currentRole the current role
|
|
*/
|
|
|
|
@Override
|
|
public void assignRolesOtherOrganization(String username,
|
|
String sourceOrganization, RolesCkanGroupOrOrg currentRole) {
|
|
|
|
checkNotNull(username);
|
|
checkNotNull(sourceOrganization);
|
|
checkNotNull(currentRole);
|
|
|
|
LOG.info("Request for assigning other roles for user " + username + ", whose current role is " + currentRole + " and organization " + sourceOrganization);
|
|
|
|
Iterator<Entry<String, String>> iterator = extendRoleInOrganization.entrySet().iterator();
|
|
LOG.debug("List of entries to check is " + extendRoleInOrganization);
|
|
while (iterator.hasNext()) {
|
|
Map.Entry<java.lang.String, java.lang.String> entry = iterator
|
|
.next();
|
|
|
|
String sourceOrg = entry.getKey();
|
|
|
|
LOG.debug("Found organization source " + sourceOrg);
|
|
if(sourceOrg.equals(sourceOrganization)){
|
|
|
|
String[] values = entry.getValue().split(DataCatalogueRunningCluster.TUPLES_SEPARATOR);
|
|
|
|
for(int i = 0; i < values.length; i++){
|
|
|
|
String destOrg = values[i].split("\\"+DataCatalogueRunningCluster.ROLE_ORGANIZATION_SEPARATOR)[0];
|
|
String role = values[i].split("\\"+DataCatalogueRunningCluster.ROLE_ORGANIZATION_SEPARATOR)[1];
|
|
|
|
LOG.debug("Role is " + role + " and organization is " + destOrg);
|
|
RolesCkanGroupOrOrg ckanRole;
|
|
if(role.equals(DataCatalogueRunningCluster.CKAN_GENERIC_ROLE))
|
|
ckanRole = currentRole;
|
|
else
|
|
ckanRole = RolesCkanGroupOrOrg.convertFromCapacity(role);
|
|
|
|
LOG.info("Checking for extra role: role is " + ckanRole + " and organization is " + destOrg);
|
|
checkRoleIntoOrganization(username, destOrg, ckanRole);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|