Utils method function created. Now it is possible to update automatically the role a user has into an organization

git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-catalogue/ckan-util-library@129147 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Costantino Perciante 2016-06-16 16:09:26 +00:00
parent 53ab6322cf
commit 0791e7f065
6 changed files with 268 additions and 351 deletions

View File

@ -7,7 +7,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.gcube.common.portal.PortalContext;
import org.gcube.common.encryption.StringEncrypter;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint;
import org.gcube.common.scope.api.ScopeProvider;
@ -31,11 +31,14 @@ public class CKanRunningCluster {
// database of the datacatalogue info
private final static String RUNTIME_DB_RESOURCE_NAME = "CKanDatabase";
private final static String PLATFORM_DB_NAME = "postgres";
// data catalogue info
private final static String RUNTIME_CATALOGUE_RESOURCE_NAME = "CKanDataCatalogue";
private final static String PLATFORM_CATALOGUE_NAME = "Tomcat";
// api key property
private final static String API_KEY_PROPERTY = "API_KEY";
// retrieved data
private List<String> datacatalogueUrls = new ArrayList<String>();
private List<String> hostsDB = new ArrayList<String>();
@ -44,12 +47,24 @@ public class CKanRunningCluster {
private String userDB;
private String passwordDB;
// this token is needed in order to assign roles to user
private String sysAdminToken;
public CKanRunningCluster(String scope) throws Exception{
if(scope == null || scope.isEmpty())
throw new Exception("Invalid scope!!");
// retrieve the current scope and save it (it will be reset later)
String currentScope = ScopeProvider.instance.get();
logger.debug("Retrieving ckan database service end point information.");
try {
List<ServiceEndpoint> resources = getConfigurationFromISFORDB(scope);
// set the scope
ScopeProvider.instance.set(scope);
List<ServiceEndpoint> resources = getConfigurationFromISFORDB();
if (resources.size() > 1) {
logger.error("Too many Runtime Resource having name " + RUNTIME_DB_RESOURCE_NAME +" in this scope");
@ -84,9 +99,9 @@ public class CKanRunningCluster {
nameDB = accessPoint.name();
// save user and password
passwordDB = accessPoint.password();
passwordDB = StringEncrypter.getEncrypter().decrypt(accessPoint.password());
userDB = accessPoint.username();
break;
}
@ -97,17 +112,10 @@ public class CKanRunningCluster {
throw new ServiceEndPointException();
}
}
} catch (Exception e) {
logger.error(e.toString());
throw e;
}
logger.debug("Retrieving ckan data catalogue service end point information.");
try {
List<ServiceEndpoint> resources = getConfigurationFromISFORCatalogueUrl(scope);
logger.debug("Retrieving ckan data catalogue service end point information and sysadmin token.");
resources = getConfigurationFromISFORCatalogueUrl();
if (resources.size() > 1) {
logger.error("Too many Runtime Resource having name " + RUNTIME_CATALOGUE_RESOURCE_NAME +" in this scope");
throw new TooManyRunningClustersException("There exist more than 1 Runtime Resource in this scope having name "
@ -132,6 +140,10 @@ public class CKanRunningCluster {
// add this host
datacatalogueUrls.add(accessPoint.address());
// retrieve sys admin token
sysAdminToken = accessPoint.propertyMap().get(API_KEY_PROPERTY).value();
sysAdminToken = StringEncrypter.getEncrypter().decrypt(sysAdminToken);
break;
@ -143,9 +155,14 @@ public class CKanRunningCluster {
throw new ServiceEndPointException();
}
}
} catch (Exception e) {
}catch(Exception e) {
logger.error(e.toString());
throw e;
}finally{
// set the scope back
ScopeProvider.instance.set(currentScope);
}
}
@ -155,59 +172,33 @@ public class CKanRunningCluster {
* @return list of endpoints for ckan database
* @throws Exception
*/
private List<ServiceEndpoint> getConfigurationFromISFORDB(String scope) throws Exception{
private List<ServiceEndpoint> getConfigurationFromISFORDB() throws Exception{
String evaluatedScope = "";
if(scope != null && !scope.isEmpty())
evaluatedScope += scope;
else{
PortalContext context = PortalContext.getConfiguration();
evaluatedScope += context.getInfrastructureName();
}
String currScope = ScopeProvider.instance.get();
ScopeProvider.instance.set(evaluatedScope);
SimpleQuery query = queryFor(ServiceEndpoint.class);
query.addCondition("$resource/Profile/Name/text() eq '"+ RUNTIME_DB_RESOURCE_NAME +"'");
query.addCondition("$resource/Profile/Platform/Name/text() eq '"+ PLATFORM_DB_NAME +"'");
DiscoveryClient<ServiceEndpoint> client = clientFor(ServiceEndpoint.class);
List<ServiceEndpoint> toReturn = client.submit(query);
ScopeProvider.instance.set(currScope);
return toReturn;
}
/**
* Retrieve endpoints information from IS for DataCatalogue URL
* @return list of endpoints for ckan data catalogue
* @throws Exception
*/
private List<ServiceEndpoint> getConfigurationFromISFORCatalogueUrl(String scope) throws Exception{
private List<ServiceEndpoint> getConfigurationFromISFORCatalogueUrl() throws Exception{
String evaluatedScope = "";
if(scope != null && !scope.isEmpty())
evaluatedScope += scope;
else{
PortalContext context = PortalContext.getConfiguration();
evaluatedScope += context.getInfrastructureName();
}
String currScope = ScopeProvider.instance.get();
ScopeProvider.instance.set(evaluatedScope);
SimpleQuery query = queryFor(ServiceEndpoint.class);
query.addCondition("$resource/Profile/Name/text() eq '"+ RUNTIME_CATALOGUE_RESOURCE_NAME +"'");
query.addCondition("$resource/Profile/Platform/Name/text() eq '"+ PLATFORM_CATALOGUE_NAME +"'");
DiscoveryClient<ServiceEndpoint> client = clientFor(ServiceEndpoint.class);
List<ServiceEndpoint> toReturn = client.submit(query);
ScopeProvider.instance.set(currScope);
return toReturn;
}
/**
* Retrieve data catalogue url
*/
@ -254,4 +245,11 @@ public class CKanRunningCluster {
public String getDataBasePassword() {
return passwordDB;
}
/**
* @return the sysAdminToken
*/
public String getSysAdminToken() {
return sysAdminToken;
}
}

View File

@ -1,79 +0,0 @@
package org.gcube.datacatalogue.ckanutillibrary;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Use this factory to retrieve an utility class instance associated to a particular scope.
* NOTE: YOU ARE SUGGESTED TO USE THIS CLASS, DO NOT INSTANCIATE THE CkanUtils OBJECT DIRECTLY.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class CKanUtilsFactory {
/**
* logger
*/
private static final Logger logger = LoggerFactory.getLogger(CKanUtilsFactory.class);
/**
* map <scope, util class for this scope>
*/
private static ConcurrentHashMap<String, CKanUtilsImpl> instanceForScopes;
/**
* this object singleton instance
*/
private static CKanUtilsFactory factoryInstance = new CKanUtilsFactory();
/**
* private constructor
*/
private CKanUtilsFactory(){
logger.debug("Instanciating factory");
instanceForScopes = new ConcurrentHashMap<String, CKanUtilsImpl>();
}
/**
* Get the factory object
*/
public static CKanUtilsFactory getInstance(){
return factoryInstance;
}
/**
* Retrieve catalogue utils class for this scope
* @param scope
* @throws Exception
*/
public CKanUtilsImpl getCkanUtilsForScope(String scope) throws Exception{
logger.debug("Requested catalogue utils for scope " + scope);
if(scope == null || scope.isEmpty()){
logger.error("Malformed scope, ignoring request");
return null;
}
if(instanceForScopes.containsKey(scope)){
logger.debug("Catalogue utils already cached for scope = " + scope + ", returning object");
return instanceForScopes.get(scope);
}
else{
logger.debug("Instanciating utils for this scope");
CKanUtilsImpl utilsForScope = new CKanUtilsImpl(scope);
// save into the map
instanceForScopes.put(scope, utilsForScope);
return utilsForScope;
}
}
}

View File

@ -1,7 +1,5 @@
package org.gcube.datacatalogue.ckanutillibrary;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
@ -17,12 +15,11 @@ import net.htmlparser.jericho.Renderer;
import net.htmlparser.jericho.Segment;
import net.htmlparser.jericho.Source;
import org.gcube.common.encryption.StringEncrypter;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.ckanutillibrary.models.CKanUserWrapper;
import org.gcube.datacatalogue.ckanutillibrary.models.ResourceBean;
import org.gcube.datacatalogue.ckanutillibrary.models.RolesIntoOrganization;
import org.gcube.datacatalogue.ckanutillibrary.models.State;
import org.gcube.datacatalogue.ckanutillibrary.utils.UtilMethods;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -56,47 +53,35 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
private String CKAN_DB_PASSWORD;
private String CKAN_DB_URL;
private Integer CKAN_DB_PORT;
private String CKAN_TOKEN_SYS;
// Connection to the db
private Connection connection;
public CKanUtilsImpl(String scope) throws Exception{
String currentScope = ScopeProvider.instance.get();
CKanRunningCluster runningInstance = new CKanRunningCluster(scope);
CKAN_DB_URL = runningInstance.getDatabaseHosts().get(0);
CKAN_DB_NAME = runningInstance.getDataBaseName();
CKAN_DB_USER = runningInstance.getDataBaseUser();
CKAN_DB_PASSWORD = runningInstance.getDataBasePassword();
logger.debug("Plain password first 3 chars are " + CKAN_DB_PASSWORD.substring(0, 3));
CKAN_TOKEN_SYS = runningInstance.getSysAdminToken();
logger.debug("Plain sys admin token first 3 chars are " + CKAN_TOKEN_SYS.substring(0, 3));
try{
CKAN_DB_PORT = runningInstance.getDatabasePorts().get(0);
CKAN_CATALOGUE_URL = runningInstance.getDataCatalogueUrl().get(0);
ScopeProvider.instance.set(scope);
CKanRunningCluster runningInstance = new CKanRunningCluster(scope);
CKAN_DB_URL = runningInstance.getDatabaseHosts().get(0);
CKAN_DB_NAME = runningInstance.getDataBaseName();
CKAN_DB_USER = runningInstance.getDataBaseUser();
CKAN_DB_PASSWORD = StringEncrypter.getEncrypter().decrypt(runningInstance.getDataBasePassword());
logger.debug("Plain password first 3 chars are " + CKAN_DB_PASSWORD.substring(0, 3));
CKAN_DB_PORT = runningInstance.getDatabasePorts().get(0);
CKAN_CATALOGUE_URL = runningInstance.getDataCatalogueUrl().get(0);
// create db connection
Class.forName("org.postgresql.Driver");
connection = DriverManager.getConnection(
"jdbc:postgresql://" + CKAN_DB_URL + ":" + CKAN_DB_PORT + "/" + CKAN_DB_NAME, CKAN_DB_USER, CKAN_DB_PASSWORD);
}catch(Exception e){
logger.error("Error while trying to connect to ckan database/catalogue ", e);
}finally{
// set the scope back
ScopeProvider.instance.set(currentScope);
}
Class.forName("org.postgresql.Driver");
connection = DriverManager.getConnection(
"jdbc:postgresql://" + CKAN_DB_URL + ":" + CKAN_DB_PORT + "/" + CKAN_DB_NAME, CKAN_DB_USER, CKAN_DB_PASSWORD);
}
@Override
public String getApiKeyFromUser(String username) {
public String getApiKeyFromUsername(String username) {
// in order to avoid errors, the username is always converted
String ckanUsername = fromOwnerToCKanOwner(username);
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
logger.debug("Request api key for user = " + username);
String apiToReturn = null;
@ -104,18 +89,19 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
String query = "SELECT \"apikey\" FROM \"user\" WHERE \"name\"=? and \"state\"=?;";
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, ckanUsername);
preparedStatement.setString(2, State.ACTIVE.toString());
preparedStatement.setString(2, State.ACTIVE.toString().toLowerCase());
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
apiToReturn = rs.getString("apikey");
break;
}
logger.debug("Api key retrieved for user " + ckanUsername);
}catch(Exception e){
logger.error("Unable to retrieve key for user " + ckanUsername, e);
}
logger.debug("Api key retrieved for user " + ckanUsername);
return apiToReturn;
}
@ -127,7 +113,7 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
String query = "SELECT * FROM \"user\" WHERE \"apikey\"=? and \"state\"=?;";
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, apiKey);
preparedStatement.setString(2, State.ACTIVE.toString());
preparedStatement.setString(2, State.ACTIVE.toString().toLowerCase());
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
@ -145,13 +131,13 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
user.setFullName(rs.getString("fullname"));
user.setEmail(rs.getString("email"));
user.setAdmin(rs.getBoolean("sysadmin"));
logger.debug("User retrieved");
break;
}
}catch(Exception e){
logger.error("Unable to retrieve user with api key " + apiKey, e);
}
logger.debug("User retrieved");
return user;
}
@ -161,7 +147,7 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
logger.debug("Requested organizations for user " + username);
// in order to avoid errors, the username is always converted
String ckanUsername = fromOwnerToCKanOwner(username);
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
List<String> organizationIds = getOrganizationsIds();
String userId = getUserIdByUsername(ckanUsername);
@ -180,7 +166,7 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
preparedStatement.setString(1, userId);
preparedStatement.setString(2, orgId);
preparedStatement.setString(3, "user");
preparedStatement.setString(4, State.ACTIVE.toString());
preparedStatement.setString(4, State.ACTIVE.toString().toLowerCase());
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
// the role within the organization doesn't matter
@ -200,18 +186,21 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
public Map<String, List<RolesIntoOrganization>> getGroupsAndRolesByUser(
String username, List<RolesIntoOrganization> rolesToMatch) {
logger.debug("Requested roles the user " + username + " has into its organizations");
logger.debug("Requested roles the user " + username + " has into his organizations");
logger.debug("Roles to check are " + rolesToMatch);
Map<String, List<RolesIntoOrganization>> toReturn = new HashMap<String, List<RolesIntoOrganization>>();
// in order to avoid errors, the username is always converted
String ckanUsername = fromOwnerToCKanOwner(username);
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
// get its key
String apiKey = getApiKeyFromUsername(ckanUsername);
// retrieve the user and if it is a sys_admin, for every organizations will be created in the map, add also
// the sys_admin role
boolean isSysAdmin = false;
if(rolesToMatch.contains(RolesIntoOrganization.SYSADMIN)){
isSysAdmin = isSysAdmin(ckanUsername);
isSysAdmin = isSysAdmin(ckanUsername, apiKey);
}
try{
@ -233,7 +222,7 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
preparedStatement.setString(1, userId);
preparedStatement.setString(2, orgId);
preparedStatement.setString(3, "user");
preparedStatement.setString(4, "active");
preparedStatement.setString(4, State.ACTIVE.toString().toLowerCase());
ResultSet rs = preparedStatement.executeQuery();
// prepare the data to put into the hashmap
@ -272,24 +261,24 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
logger.debug("Request user id whose username is = " + username);
// in order to avoid errors, the username is always converted
String ckanUsername = fromOwnerToCKanOwner(username);
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
String userId = null;
try{
String query = "SELECT \"id\" FROM \"user\" WHERE \"name\"=? and \"state\"=?;";
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, ckanUsername);
preparedStatement.setString(2, State.ACTIVE.toString());
preparedStatement.setString(2, State.ACTIVE.toString().toLowerCase());
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
userId = rs.getString("id");
break;
}
logger.debug("User id retrieved for " + ckanUsername + " "+ userId);
}catch(Exception e){
logger.error("Unable to retrieve user with name " + ckanUsername, e);
}
logger.debug("User id retrieved");
return userId;
}
@ -298,28 +287,17 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
* @return
*/
private List<String> getOrganizationsIds(){
logger.debug("Request organization ids");
List<String> toReturn = new ArrayList<String>();
CkanClient client = new CkanClient(CKAN_CATALOGUE_URL);
List<CkanOrganization> orgs = client.getOrganizationList();
try{
String query = "SELECT \"id\" FROM \"group\" WHERE \"is_organization\"=? and \"state\"=?;";
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setBoolean(1, true);
preparedStatement.setString(2, State.ACTIVE.toString());
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
toReturn.add(rs.getString("id"));
}
logger.debug("Organizations' ids retrieved");
}catch(Exception e){
logger.error("Unable to retrieve list of organization ids", e);
for (CkanOrganization ckanOrganization : orgs) {
logger.debug("Retrieved org " + ckanOrganization.getName());
toReturn.add(ckanOrganization.getId());
}
return toReturn;
}
@Override
public String getCKANDBUrl() {
return CKAN_DB_URL;
return toReturn;
}
@Override
@ -333,9 +311,10 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
logger.debug("Requested organizations for user " + username);
// in order to avoid errors, the username is always converted
String ckanUsername = fromOwnerToCKanOwner(username);
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
List<CkanOrganization> orgs = getOrganizationsByUser(ckanUsername);
List<String> orgsName = new ArrayList<String>();
for (CkanOrganization ckanOrganization : orgs) {
orgsName.add(ckanOrganization.getName());
@ -350,8 +329,7 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
public String findLicenseIdByLicense(String chosenLicense) {
logger.debug("Requested license id");
String ckanPortalUrl = getCatalogueUrl();
CkanClient client = new CkanClient(ckanPortalUrl);
CkanClient client = new CkanClient(CKAN_CATALOGUE_URL);
//retrieve the list of available licenses
List<CkanLicense> licenses = client.getLicenseList();
@ -370,10 +348,9 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
logger.debug("Request for CKAN licenses");
// get the url and the api key of the user
String ckanPortalUrl = getCatalogueUrl();
List<String> result = new ArrayList<String>();
CkanClient client = new CkanClient(ckanPortalUrl);
CkanClient client = new CkanClient(CKAN_CATALOGUE_URL);
//retrieve the list of available licenses
List<CkanLicense> licenses = client.getLicenseList();
@ -390,27 +367,15 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
@Override
public boolean setDatasetPrivate(boolean priv, String organizationId,
String datasetId, String username) {
String datasetId, String apiKey) {
String pathSetPrivate = "/api/3/action/bulk_update_private";
String pathSetPublic = "/api/3/action/bulk_update_public";
String token = null;
// in order to avoid errors, the username is always converted
String ckanUsername = fromOwnerToCKanOwner(username);
if(ckanUsername == null || ckanUsername.isEmpty()){
logger.error("The owner parameter is mandatory");
if(apiKey == null || apiKey.isEmpty()){
logger.error("The apiKey parameter is mandatory");
return false;
}else{
token = getApiKeyFromUser(ckanUsername);
if(token == null){
logger.error("Unable to retrieve user's token");
return false;
}
}
// Request parameters to be replaced
@ -430,7 +395,7 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
if(priv){
try {
HttpPost request = new HttpPost(CKAN_CATALOGUE_URL + pathSetPrivate);
request.addHeader("Authorization", token);
request.addHeader("Authorization", apiKey);
StringEntity params = new StringEntity(parameter);
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
@ -447,7 +412,7 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
try {
HttpPost request = new HttpPost(CKAN_CATALOGUE_URL + pathSetPublic);
StringEntity params =new StringEntity(parameter);
request.addHeader("Authorization", token);
request.addHeader("Authorization", apiKey);
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
logger.debug("[PUBLIC]Response code is " + response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase());
@ -464,43 +429,18 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
return false;
}
/**
* Utility method to check if a something at this url actually exists
* @param URLName
* @return
*/
private static boolean resourceExists(String URLName){
try {
HttpURLConnection.setFollowRedirects(true);
HttpURLConnection con = (HttpURLConnection) new URL(URLName).openConnection();
con.setRequestMethod("HEAD");
logger.debug("Return code is " + con.getResponseCode());
return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
}
catch (Exception e) {
logger.error("Exception while checking url", e);
return false;
}
}
@Override
public String addResourceToDataset(ResourceBean resourceBean) {
public String addResourceToDataset(ResourceBean resourceBean, String apiKey) {
logger.debug("Request to add a resource described by this bean " + resourceBean);
try{
if(resourceExists(resourceBean.getUrl())){
// retrieve ckan's catalog url
String ckanPortalUrl = getCatalogueUrl();
if(UtilMethods.resourceExists(resourceBean.getUrl())){
// in order to avoid errors, the username is always converted
String ckanUsername = fromOwnerToCKanOwner(resourceBean.getOwner());
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(resourceBean.getOwner());
// retrieve the api key for this user
String apiKey = getApiKeyFromUser(ckanUsername);
CkanResource resource = new CkanResource(ckanPortalUrl, resourceBean.getDatasetId());
CkanResource resource = new CkanResource(CKAN_CATALOGUE_URL, resourceBean.getDatasetId());
resource.setName(resourceBean.getName());
// escape description
@ -513,7 +453,7 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
resource.setOwner(ckanUsername);
// Checked client
CheckedCkanClient client = new CheckedCkanClient(ckanPortalUrl, apiKey);
CheckedCkanClient client = new CheckedCkanClient(CKAN_CATALOGUE_URL, apiKey);
CkanResource createdRes = client.createResource(resource);
if(createdRes != null){
@ -532,16 +472,13 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
}
@Override
public boolean deleteResourceFromDataset(String username, String resourceId) {
public boolean deleteResourceFromDataset(String resourceId, String apiKey) {
logger.error("Request to delete a resource with id " + resourceId + " coming by user " + username);
// in order to avoid errors, the username is always converted
String ckanUsername = fromOwnerToCKanOwner(username);
logger.error("Request to delete a resource with id " + resourceId + " coming by user with key " + apiKey);
try{
CheckedCkanClient client = new CheckedCkanClient(getCatalogueUrl(), getApiKeyFromUser(ckanUsername));
CheckedCkanClient client = new CheckedCkanClient(CKAN_CATALOGUE_URL, apiKey);
client.deleteResource(resourceId);
return true;
@ -553,23 +490,8 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
return false;
}
/**
* Generate the catalogue's dataset name from its title
* @param title
* @return
*/
private String nameFromTitle(String title) {
String convertedName = title.replaceAll(" ", "_");
convertedName = convertedName.replaceAll("\\.", "_");
convertedName = convertedName.toLowerCase();
if(convertedName.endsWith("_"))
convertedName = convertedName.substring(0, convertedName.length() - 2);
return convertedName;
}
@Override
public String createCKanDataset(String username, String withId,
public String createCKanDataset(String apiKey, String withId,
String title, String organizationNameOrId, String author,
String authorMail, String maintainer, String maintainerMail,
long version, String description, String licenseId,
@ -578,10 +500,10 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
logger.debug("Request for dataset creation");
// in order to avoid errors, the username is always converted
String ckanUsername = fromOwnerToCKanOwner(username);
CheckedCkanClient client = new CheckedCkanClient(CKAN_CATALOGUE_URL, apiKey);
CheckedCkanClient client = new CheckedCkanClient(getCatalogueUrl(), getApiKeyFromUser(ckanUsername));
// get client from apiKey
String ckanUsername = getUserFromApiKey(apiKey).getName();
// create the base dataset and fill it
CkanDataset dataset = new CkanDataset();
@ -590,7 +512,7 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
dataset.setId(withId);
// get the name from the title
dataset.setName(nameFromTitle(title));
dataset.setName(UtilMethods.nameFromTitle(title));
dataset.setTitle(title);
CkanOrganization orgOwner = client.getOrganization(organizationNameOrId);
@ -696,7 +618,7 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
}catch(Exception e){
// try to update
logger.error("Error while creating the dataset, probably it already exists.", e);
logger.error("Error while creating the dataset.", e);
}
@ -704,19 +626,17 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
}
@Override
public String getUrlFromDatasetIdOrName(String username, String datasetIdOrName) {
public String getUrlFromDatasetIdOrName(String apiKey, String datasetIdOrName) {
logger.debug("Request coming for dataset url of dataset with name/id " + datasetIdOrName);
String ckanUsername = fromOwnerToCKanOwner(username);
// the url of the dataset looks like "getCatalogueUrl() + /dataset/ + dataset name"
try{
CheckedCkanClient client = new CheckedCkanClient(getCatalogueUrl(), getApiKeyFromUser(ckanUsername));
CheckedCkanClient client = new CheckedCkanClient(CKAN_CATALOGUE_URL, apiKey);
CkanDataset dataset = client.getDataset(datasetIdOrName);
if(dataset != null){
return getCatalogueUrl() + "/dataset/" + dataset.getName();
return CKAN_CATALOGUE_URL + "/dataset/" + dataset.getName();
}
}catch(Exception e){
logger.error("Error while retrieving dataset with id/name=" + datasetIdOrName, e);
@ -724,34 +644,77 @@ public class CKanUtilsImpl implements CKanUtilsInterface{
return null;
}
/**
* Ckan username has _ instead of . (that is, costantino.perciante -> costantino_perciante)
* @param owner
* @return
*/
private static String fromOwnerToCKanOwner(String owner){
return owner.replaceAll("\\.", "_");
}
@Override
public boolean checkRole(String username, String organizationName,
public void checkRole(String username, String organizationName,
RolesIntoOrganization correspondentRoleToCheck) {
// TODO it must be defined
return true;
logger.debug("Request for checking if " + username + " into " + organizationName + " has role " + correspondentRoleToCheck);
if(correspondentRoleToCheck.equals(RolesIntoOrganization.SYSADMIN)){
logger.debug("SYSADMIN role cannot be created programmatically... The user role will be turned into admin");
correspondentRoleToCheck = RolesIntoOrganization.ADMIN;
}
// convert ckan username
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
// we need to use the apis to make this
String path = "/api/3/action/organization_member_create";
// Request parameters to be replaced
String parameter = "{"
+ "\"id\":\"ORGANIZATION_ID_NAME\","
+ "\"username\":\"USERNAME_ID_NAME\","
+ "\"role\":\"ROLE\""
+ "}";
// replace those values
parameter = parameter.replace("ORGANIZATION_ID_NAME", organizationName.toLowerCase());
parameter = parameter.replace("USERNAME_ID_NAME", ckanUsername);
parameter = parameter.replace("ROLE", correspondentRoleToCheck.toString().toLowerCase());
logger.debug("API request for organization membership is going to be " + parameter);
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
try {
HttpPost request = new HttpPost(CKAN_CATALOGUE_URL + path);
request.addHeader("Authorization", CKAN_TOKEN_SYS); // sys token
StringEntity params = new StringEntity(parameter);
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
logger.debug("Response code is " + response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase());
if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
return;
}catch (Exception ex) {
logger.error("Error while trying to change the role for this user ", ex);
}
return;
}
@Override
public boolean isSysAdmin(String username) {
// in order to avoid errors, the username is always converted
String ckanUsername = fromOwnerToCKanOwner(username);
CheckedCkanClient checkedClient = new CheckedCkanClient(getCatalogueUrl(), getApiKeyFromUser(ckanUsername));
CkanUser user = checkedClient.getUser(getUserIdByUsername(ckanUsername));
return user.isSysadmin();
public boolean isSysAdmin(String username, String apiKey) {
try{
// in order to avoid errors, the username is always converted
String ckanUsername = UtilMethods.fromUsernameToCKanUsername(username);
CheckedCkanClient checkedClient = new CheckedCkanClient(CKAN_CATALOGUE_URL, apiKey);
CkanUser user = checkedClient.getUser(getUserIdByUsername(ckanUsername));
return user.isSysadmin();
}catch(Exception e){
logger.error("Failed to check if the user " + username + " has role sysadmin", e);
}
return false;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
logger.debug("Closing connection on finalize()");
connection.close();
}

View File

@ -20,11 +20,11 @@ public interface CKanUtilsInterface {
* @param username
* @return an API_KEY string on success, null otherwise
*/
public String getApiKeyFromUser(String username);
public String getApiKeyFromUsername(String username);
/**
* Retrieve the user given the API_KEY (the user is retrieved if it is active).
* @param username
* @param the user api key
* @return an API_KEY string
*/
public CKanUserWrapper getUserFromApiKey(String apiKey);
@ -54,15 +54,10 @@ public interface CKanUtilsInterface {
/**
* Return the ckan catalogue url in this scope.
* @return the catalogue url or exception if not found
* @return the catalogue url
*/
public String getCatalogueUrl();
/**
* Return the url of the database
*/
public String getCKANDBUrl();
/**
* Get the list of licenses' titles.
* @return the list of licenses' titles
@ -81,29 +76,30 @@ public interface CKanUtilsInterface {
* @param priv
* @param organizationId
* @param datasetId
* @param owner
* @param apiKey the user's api key
* @return true on success, false otherwise
*/
public boolean setDatasetPrivate(boolean priv, String organizationId, String datasetId, String owner);
public boolean setDatasetPrivate(boolean priv, String organizationId, String datasetId, String apiKey);
/**
* Add a resource described by the bean to the dataset id into resource.datasetId
* @param resource
* @param apiKey the user api key
* @return String the id of the resource on success, null otherwise
*/
public String addResourceToDataset(ResourceBean resource);
public String addResourceToDataset(ResourceBean resource, String apiKey);
/**
* Remove the resource with id resourceId from the dataset in which it is.
* @param username
* @param resourceId
* @param apiKey the user's api key
* @return true on success, false otherwise.
*/
public boolean deleteResourceFromDataset(String username, String resourceId);
public boolean deleteResourceFromDataset(String resourceId, String apiKey);
/**
* Create a dataset with those information.
* @param username
* @param apiKey
* @param withId
* @param title
* @param organizationNameOrId
@ -120,24 +116,25 @@ public interface CKanUtilsInterface {
* @param setPublic (manage visibility)
* @return the id of the dataset on success, null otherwise
*/
public String createCKanDataset(String username, String withId, String title, String organizationNameOrId, String author,
public String createCKanDataset(String apiKey, String withId, String title, String organizationNameOrId, String author,
String authorMail, String maintainer, String maintainerMail, long version, String description, String licenseId,
List<String> tags, Map<String, String> customFields, List<ResourceBean> resources, boolean setPublic);
/**
* Given the id or the name of the dataset it returns its current url (e.g., http://ckan-catalogue-address.org/dataset/dataset-name)
* @param username
* @param apiKey
* @param datasetId
* @return The url of the dataset on success, null otherwise
*/
public String getUrlFromDatasetIdOrName(String username, String datasetIdOrName);
public String getUrlFromDatasetIdOrName(String apiKey, String datasetIdOrName);
/**
* Check if this user is a sysadmin
* Check if this user is a sysadmin. The api key is used to authorize this call.
* @param username
* @param apiKey the current user's api key
* @return true on success, false otherwise
*/
public boolean isSysAdmin(String username);
public boolean isSysAdmin(String username, String apiKey);
/**
* Check if this role is present for this user in that organization. If it is not present we need to add it.
@ -145,6 +142,6 @@ public interface CKanUtilsInterface {
* @param organizationName
* @param correspondentRoleToCheck
*/
public boolean checkRole(String username, String organizationName,
public void checkRole(String username, String organizationName,
RolesIntoOrganization correspondentRoleToCheck);
}

View File

@ -0,0 +1,70 @@
package org.gcube.datacatalogue.ckanutillibrary.utils;
import java.net.HttpURLConnection;
import java.net.URL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Some utility methods used within the library.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class UtilMethods {
private static final Logger logger = LoggerFactory.getLogger(UtilMethods.class);
/**
* Ckan username has _ instead of . (that is, costantino.perciante -> costantino_perciante)
* @param owner
* @return
*/
public static String fromUsernameToCKanUsername(String username){
if(username == null)
return null;
return username.replaceAll("\\.", "_");
}
/**
* Generate the catalogue's dataset name from its title
* @param title
* @return
*/
public static String nameFromTitle(String title) {
if(title == null)
return null;
String convertedName = title.replaceAll(" ", "_");
convertedName = convertedName.replaceAll("\\.", "_");
convertedName = convertedName.toLowerCase();
if(convertedName.endsWith("_"))
convertedName = convertedName.substring(0, convertedName.length() - 2);
return convertedName;
}
/**
* Utility method to check if a something at this url actually exists
* @param URLName
* @return
*/
public static boolean resourceExists(String URLName){
if(URLName == null || URLName.isEmpty())
return false;
try {
HttpURLConnection.setFollowRedirects(true);
HttpURLConnection con = (HttpURLConnection) new URL(URLName).openConnection();
con.setRequestMethod("HEAD");
logger.debug("Return code is " + con.getResponseCode());
return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
}
catch (Exception e) {
logger.error("Exception while checking url", e);
return false;
}
}
}

View File

@ -8,8 +8,6 @@ import org.gcube.datacatalogue.ckanutillibrary.models.CKanUserWrapper;
import org.gcube.datacatalogue.ckanutillibrary.models.RolesIntoOrganization;
import org.slf4j.LoggerFactory;
import eu.trentorise.opendata.jackan.CheckedCkanClient;
import eu.trentorise.opendata.jackan.model.CkanDataset;
import eu.trentorise.opendata.jackan.model.CkanOrganization;
public class TestCKanLib {
@ -18,10 +16,14 @@ public class TestCKanLib {
CKanUtilsImpl instance;
//@Before
//@Test
public void before() throws Exception{
instance = new CKanUtilsImpl("/gcube");
List<String> orgs = instance.getOrganizationsNamesByUser("costantino.perciante");
for (String string : orgs) {
System.out.println("org is " + string);
}
}
@ -31,7 +33,7 @@ public class TestCKanLib {
logger.debug("Testing getApiKeyFromUser");
String username = "francescomangiacrapa";
String key = instance.getApiKeyFromUser(username);
String key = instance.getApiKeyFromUsername(username);
System.out.println("key for " + username + " is " + key);
}
@ -76,38 +78,4 @@ public class TestCKanLib {
System.out.println("organizations for user " + username + " are " + map);
}
//@Test
public void testFactory() throws Exception{
System.out.println("Creating factory object");
CKanUtilsImpl obj = CKanUtilsFactory.getInstance().getCkanUtilsForScope("/gcube");
System.out.println("Object created " + obj.getCatalogueUrl());
}
//@Test
public void deleteUserDataset() throws Exception{
String url = CKanUtilsFactory.getInstance().getCkanUtilsForScope("/gcube").getCatalogueUrl();
String token = CKanUtilsFactory.getInstance().getCkanUtilsForScope("/gcube").getApiKeyFromUser("costantino_perciante");
CheckedCkanClient client = new CheckedCkanClient(url, token);
List<String> datasetNames = client.getDatasetList();
System.out.println("datasetNames is " + datasetNames);
for (String name : datasetNames) {
CkanDataset dataset = new CkanDataset(name);
if(dataset.getAuthor().equals("costantino_perciante")){
//client.deleteDataset(name);
System.out.println("Name is " + name);
}
}
}
}