1421 lines
45 KiB
Java
1421 lines
45 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.io.BufferedReader;
|
|
import java.io.InputStreamReader;
|
|
import java.io.OutputStream;
|
|
import java.net.HttpURLConnection;
|
|
import java.net.URL;
|
|
import java.net.URLConnection;
|
|
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.authorization.library.provider.SecurityTokenProvider;
|
|
import org.gcube.common.scope.api.ScopeProvider;
|
|
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.GCubeUtils.GCUBE_SCOPE_LEVEL;
|
|
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.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
|
|
* @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);
|
|
}
|
|
|
|
@Override
|
|
public String getCatalogueUrl() {
|
|
return CKAN_CATALOGUE_URL;
|
|
}
|
|
|
|
|
|
@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;
|
|
}
|
|
}
|
|
|
|
|
|
@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;
|
|
}
|
|
|
|
@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;
|
|
}
|
|
|
|
@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.ckanutillibrary.server.DataCatalogue#getDataset(java.
|
|
* lang.String, java.lang.String)
|
|
*/
|
|
@Override
|
|
public CkanDataset getDataset(String datasetId, String apiKey) {
|
|
LOG.info("Request ckan dataset with id " + datasetId);
|
|
|
|
// checks
|
|
checkNotNull(datasetId);
|
|
checkArgument(!datasetId.isEmpty());
|
|
|
|
try {
|
|
|
|
if (apiKey != null && !apiKey.isEmpty()) {
|
|
LOG.info("API-KEY found. Calling the " + ExtendCkanClient.class.getSimpleName());
|
|
ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, apiKey);
|
|
return client.getDataset(datasetId);
|
|
}
|
|
|
|
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 api-key or gcube-token found. Calling Ckan Client without API-KEY");
|
|
return ckanCaller.getDataset(datasetId);
|
|
|
|
} catch (Exception e) {
|
|
LOG.error("Unable to retrieve such dataset, returning null ...", e);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
@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;
|
|
}
|
|
|
|
|
|
@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;
|
|
|
|
}
|
|
|
|
@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
|
|
* @param entityContext
|
|
* @param entityName
|
|
*/
|
|
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;
|
|
}
|
|
|
|
// /**
|
|
// * Retrieve an url for the tuple scope, entity, entity name
|
|
// * @param context
|
|
// * @param entityContext
|
|
// * @param entityName
|
|
// */
|
|
// private String getUrlForProduct(String context, EntityContext entityContext, String entityName){
|
|
//
|
|
// String toReturn = null;
|
|
//
|
|
// try {
|
|
// LOG.debug("URI-Resolver URL: "+getUriResolverUrl());
|
|
// URL url = new URL(getUriResolverUrl());
|
|
// URLConnection con = url.openConnection();
|
|
// HttpURLConnection http = (HttpURLConnection)con;
|
|
// http.setRequestMethod("POST"); // PUT is another valid option
|
|
// http.setDoOutput(true);
|
|
// http.setRequestProperty("Content-Type", ContentType.APPLICATION_JSON.toString());
|
|
//
|
|
// JSONObject requestEntity = new JSONObject();
|
|
// requestEntity.put("gcube_scope", context);
|
|
// requestEntity.put("entity_context", entityContext.toString());
|
|
// requestEntity.put("entity_name", entityName);
|
|
//
|
|
// try(OutputStream os = con.getOutputStream()) {
|
|
// byte[] input = requestEntity.toJSONString().getBytes("utf-8");
|
|
// os.write(input, 0, input.length);
|
|
// }
|
|
//
|
|
// try (BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"))) {
|
|
// StringBuilder response = new StringBuilder();
|
|
// String responseLine = null;
|
|
// while ((responseLine = br.readLine()) != null) {
|
|
// response.append(responseLine.trim());
|
|
// }
|
|
// toReturn = response.toString();
|
|
// }
|
|
//
|
|
//
|
|
// }catch (Exception e) {
|
|
// e.printStackTrace();
|
|
// }
|
|
//
|
|
// return toReturn;
|
|
// }
|
|
|
|
@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;
|
|
}
|
|
|
|
@Override
|
|
public String getUriResolverUrl() {
|
|
return URI_RESOLVER_URL;
|
|
}
|
|
|
|
/**
|
|
* Check if the manage product is enabled
|
|
* @return
|
|
*/
|
|
@Override
|
|
public boolean isManageProductEnabled() {
|
|
return MANAGE_PRODUCT_BUTTON;
|
|
}
|
|
|
|
@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;
|
|
}
|
|
|
|
@Override
|
|
public boolean isNotificationToUsersEnabled() {
|
|
return ALERT_USERS_ON_POST_CREATION;
|
|
}
|
|
|
|
|
|
@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;
|
|
}
|
|
|
|
@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;
|
|
}
|
|
|
|
@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;
|
|
}
|
|
|
|
@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;
|
|
}
|
|
|
|
@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;
|
|
|
|
}
|
|
|
|
@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;
|
|
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
@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;
|
|
}
|
|
}
|
|
|
|
@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
|
|
* @param organizationName
|
|
* @param correspondentRoleToCheck
|
|
* @return true if he has the role, false otherwise
|
|
*/
|
|
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
|
|
* @param client
|
|
* @return
|
|
*/
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
@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;
|
|
}
|
|
|
|
@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
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
@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;
|
|
}
|
|
|
|
@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;
|
|
}
|
|
|
|
@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!");
|
|
|
|
try {
|
|
|
|
//Business logic to pass the organization name to gCat if and only if the scope is of ROOT or VO (not VRE)
|
|
String scope = ScopeProvider.instance.get();
|
|
|
|
if(scope==null)
|
|
throw new Exception("No scope detected. You must set it");
|
|
|
|
GCUBE_SCOPE_LEVEL gCubeScopeLevel = GCubeUtils.toGCubeLevel(scope);
|
|
String toPassOrganizationToGcat = null;
|
|
|
|
if(gCubeScopeLevel!=null) {
|
|
switch (gCubeScopeLevel) {
|
|
case ROOT:
|
|
case VO:
|
|
toPassOrganizationToGcat = organizationName;
|
|
break;
|
|
case VRE:
|
|
toPassOrganizationToGcat = null;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 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);
|
|
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");
|
|
|
|
//TODO FOLLOWING OPERATIONS NOT SHOULD LONGER NEEDED ON DATASET CREATION, MUST BE CHECKED with @LUCA
|
|
|
|
// // set visibility
|
|
// boolean visibilitySet = setDatasetPrivate(
|
|
// !setPublic, // swap to private
|
|
// res.getOrganization().getId(),
|
|
// res.getId(),
|
|
// CKAN_TOKEN_SYS); // use sysadmin api key to be sure it will be set
|
|
//
|
|
// logger.info("Was visibility set to " + (setPublic ? "public" : "private") + "? " + visibilitySet);
|
|
//
|
|
// // set searchable to true if dataset visibility is private
|
|
// if(!setPublic){ // (swap to private)
|
|
// boolean searchableSet = setSearchableField(res.getId(), true);
|
|
// logger.info("Was searchable set to True? " + searchableSet);
|
|
// }
|
|
// return res.getId();
|
|
|
|
|
|
return toCkanDataset.getId();
|
|
}
|
|
}catch (Exception e) {
|
|
LOG.error("Error on creating the dataset: ", e);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
@Override
|
|
public boolean patchFieldsForDataset(String datasetIdOrName, Map<String, String> mapFields) throws Exception {
|
|
LOG.info("Called patch the fields " + 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());
|
|
}
|
|
|
|
}
|
|
|
|
@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());
|
|
}
|
|
|
|
}
|
|
|
|
|
|
@Override
|
|
public String addResourceToDataset(ResourceBean resourceBean) throws Exception {
|
|
LOG.info("Request to add a resource described by this bean " + resourceBean);
|
|
|
|
// checks
|
|
checkNotNull(resourceBean);
|
|
checkNotNull(resourceBean.getUrl());
|
|
|
|
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());
|
|
}
|
|
|
|
try {
|
|
|
|
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.debug("Resource " + createdRes.getName() + " added correclty");
|
|
return createdRes.getId();
|
|
}
|
|
}catch (Exception e) {
|
|
LOG.error("Unable to add the resource "+resourceBean, e);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public boolean deleteResourceFromDataset(String resourceId) throws Exception {
|
|
LOG.info("Request to delete a resource with id " + resourceId);
|
|
|
|
// checks
|
|
checkNotNull(resourceId);
|
|
checkArgument(!resourceId.isEmpty());
|
|
|
|
try{
|
|
CkanResource theResource = ckanCaller.getResource(resourceId);
|
|
gCatCaller.deleteResource(theResource.getPackageId(), resourceId);
|
|
return true;
|
|
|
|
}catch(Exception e){
|
|
LOG.error("Unable to delete resource whose id is " + resourceId, e);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
@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;
|
|
}
|
|
|
|
|
|
@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;
|
|
}
|
|
|
|
|
|
//TODO HAS TO BE REVISITED by gCAT
|
|
@Override
|
|
public boolean assignDatasetToGroup(String groupNameOrId, String datasetNameOrId) {
|
|
return assignDatasetToGroupBody(groupNameOrId, datasetNameOrId, false);
|
|
|
|
}
|
|
|
|
/**
|
|
* The real body of the assignDatasetToGroup
|
|
* @param groupNameOrId
|
|
* @param datasetNameOrId
|
|
* @param apiKey
|
|
* @param addOnParents
|
|
* @return
|
|
*/
|
|
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 uniqueGroups
|
|
* @param catalogue
|
|
* @param user's 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
|
|
*
|
|
*
|
|
*******************************************************************************/
|
|
|
|
@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);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|