ckan-util-library/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsImpl.java

419 lines
13 KiB
Java
Raw Normal View History

package org.gcube.datacatalogue.ckanutillibrary;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.ROLES_IN_ORGANIZATION;
import org.gcube.datacatalogue.ckanutillibrary.models.STATE;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.trentorise.opendata.jackan.CkanClient;
import eu.trentorise.opendata.jackan.internal.org.apache.http.HttpResponse;
import eu.trentorise.opendata.jackan.internal.org.apache.http.HttpStatus;
import eu.trentorise.opendata.jackan.internal.org.apache.http.client.methods.HttpPost;
import eu.trentorise.opendata.jackan.internal.org.apache.http.entity.StringEntity;
import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.CloseableHttpClient;
import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.HttpClientBuilder;
import eu.trentorise.opendata.jackan.model.CkanLicense;
import eu.trentorise.opendata.jackan.model.CkanOrganization;
/**
* This is the Ckan Utils implementation class.
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
*
*/
public class CKanUtilsImpl implements CKanUtilsInterface{
private static final Logger logger = LoggerFactory.getLogger(CKanUtilsImpl.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;
// Connection to the db
private static Connection connection;
public CKanUtilsImpl(String scope) throws Exception{
try{
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, 2));
// for next versions TODO
//CKAN_DB_PASSWORD = StringEncrypter.getEncrypter().decrypt(runningInstance.getDataBasePassword(), scope);
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 discovering ckan information in the infrastructure", e);
}finally{
ScopeProvider.instance.reset();
}
}
@Override
public String getApiKeyFromUser(String username) {
logger.debug("Request api key for user = " + username);
String apiToReturn = null;
try{
String query = "SELECT \"apikey\" FROM \"user\" WHERE \"name\"=?";
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, username);
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
apiToReturn = rs.getString("apikey");
break;
}
}catch(Exception e){
logger.error("Unable to retrieve key for user " + username, e);
}
logger.debug("Api key retrieved for user " + username);
return apiToReturn;
}
@Override
public CKanUserWrapper getUserFromApiKey(String apiKey) {
logger.debug("Request user whose api key is = " + apiKey);
CKanUserWrapper user = new CKanUserWrapper();
try{
String query = "SELECT * FROM \"user\" WHERE \"apikey\"=?;";
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, apiKey);
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
// check if it is active
if(STATE.deleted.equals(rs.getString("state")))
break;
user.setId(rs.getString("id"));
user.setName(rs.getString("name"));
user.setApiKey(apiKey);
user.setCreationTimestamp(rs.getTimestamp("created").getTime());
user.setAbout(rs.getString("about"));
user.setOpenId(rs.getString("openid"));
user.setFullName(rs.getString("fullname"));
user.setEmail(rs.getString("email"));
user.setAdmin(rs.getBoolean("sysadmin"));
break;
}
}catch(Exception e){
logger.error("Unable to retrieve user with api key " + apiKey);
}
logger.debug("User retrieved");
return user;
}
@Override
public List<CkanOrganization> getOrganizationsByUser(String username) {
logger.debug("Requested organizations for user " + username);
List<String> organizationIds = getOrganizationsIds();
String userId = getUserIdByUsername(username);
// list to return
List<CkanOrganization> toReturn = new ArrayList<CkanOrganization>();
// get the CkanClient to retrieve the organization from the id
CkanClient client = new CkanClient("https://ckan-d-d4s.d4science.org");
try{
// for each org id, check if the user is included
for (String orgId : organizationIds) {
String query = "SELECT * FROM \"member\" WHERE \"table_id\"=? and \"group_id\"=? and \"table_name\"=?; ";
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, userId);
preparedStatement.setString(2, orgId);
preparedStatement.setString(3, "user");
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
// the role within the organization doesn't matter
logger.debug("User " + username + " belongs to organization with id " + orgId);
toReturn.add(client.getOrganization(orgId));
}
}
}catch(Exception e){
logger.error("Unable to get user's organizations", e);
}
return toReturn;
}
@Override
public Map<String, List<ROLES_IN_ORGANIZATION>> getGroupsAndRolesByUser(
String username, List<ROLES_IN_ORGANIZATION> rolesToMatch) {
logger.debug("Requested roles the user " + username + " has into its organizations");
logger.debug("Roles to check are " + rolesToMatch);
Map<String, List<ROLES_IN_ORGANIZATION>> toReturn = new HashMap<String, List<ROLES_IN_ORGANIZATION>>();
try{
// get id from the user
String userId = getUserIdByUsername(username);
// use the above method to require the list of user's organizations
List<CkanOrganization> usersOrganizations = getOrganizationsByUser(username);
for (CkanOrganization ckanOrganization : usersOrganizations) {
// get the org id
String orgId = ckanOrganization.getId();
// go to the member table, that says which role has this user into the org
String query = "SELECT * FROM \"member\" WHERE \"table_id\"=? and \"group_id\"=? and \"table_name\"=?;";
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, userId);
preparedStatement.setString(2, orgId);
preparedStatement.setString(3, "user");
ResultSet rs = preparedStatement.executeQuery();
// prepare the data to put into the hashmap
List<ROLES_IN_ORGANIZATION> rolesIntoOrg = new ArrayList<ROLES_IN_ORGANIZATION>();
while(rs.next()){
// check
String role = rs.getString("capacity");
if(rolesToMatch.contains(ROLES_IN_ORGANIZATION.valueOf(role))){
rolesIntoOrg.add(ROLES_IN_ORGANIZATION.valueOf(role));
System.out.println("User " + username + " has role " + role + " into organization " + ckanOrganization.getName());
}
}
if(!rolesIntoOrg.isEmpty())
toReturn.put(orgId, rolesIntoOrg);
}
}catch(Exception e){
logger.error("Unable to analyze user's roles", e);
}
return toReturn;
}
/**
* Returns the user id given his username
* @param username
* @return the id on success, null otherwise
*/
private String getUserIdByUsername(String username) {
logger.debug("Request user id whose username is = " + username);
String userId = null;
try{
String query = "SELECT \"id\" FROM \"user\" WHERE \"name\"=? and \"state\"=?;";
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, username);
preparedStatement.setString(2, STATE.active.toString());
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
userId = rs.getString("id");
break;
}
}catch(Exception e){
logger.error("Unable to retrieve user with name " + username);
}
logger.debug("User id retrieved");
return userId;
}
/**
* Retrieve the list of organizations ids
* @return
*/
private List<String> getOrganizationsIds(){
logger.debug("Request organization ids");
List<String> toReturn = new ArrayList<String>();
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"));
}
}catch(Exception e){
logger.error("Unable to retrieve list of organization ids");
}
logger.debug("Organizations' ids retrieved");
return toReturn;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
logger.debug("Closing connection on finalize()");
connection.close();
}
@Override
public String getCKANDBUrl() {
return CKAN_DB_URL;
}
@Override
public String getCatalogueUrl() {
return CKAN_CATALOGUE_URL;
}
@Override
public List<String> getOrganizationsNamesByUser(String username) {
List<CkanOrganization> orgs = getOrganizationsByUser(username);
List<String> orgsName = new ArrayList<String>();
for (CkanOrganization ckanOrganization : orgs) {
orgsName.add(ckanOrganization.getName());
logger.debug("Organization name is " + ckanOrganization.getName());
}
return orgsName;
}
@Override
public String findLicenseIdByLicense(String chosenLicense) {
logger.debug("Requested license id");
String ckanPortalUrl = getCatalogueUrl();
CkanClient client = new CkanClient(ckanPortalUrl);
//retrieve the list of available licenses
List<CkanLicense> licenses = client.getLicenseList();
for (CkanLicense ckanLicense : licenses) {
if(ckanLicense.getTitle().equals(chosenLicense))
return ckanLicense.getId();
}
return null;
}
@Override
public List<String> getLicenseTitles() {
logger.info("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);
//retrieve the list of available licenses
List<CkanLicense> licenses = client.getLicenseList();
for (CkanLicense ckanLicense : licenses) {
result.add(ckanLicense.getTitle());
logger.debug("License is " + ckanLicense.getTitle() + " and id " + ckanLicense.getId());
}
return result;
}
@Override
public boolean setDatasetPrivate(boolean priv, String organizationId,
String datasetId, String owner) {
String pathSetPrivate = "/api/3/action/bulk_update_private";
String pathSetPublic = "/api/3/action/bulk_update_public";
String token = null;
if(owner == null || owner.isEmpty()){
logger.error("The owner parameter is mandatory");
return false;
}else{
token = getApiKeyFromUser(owner);
if(token == null){
logger.error("Unable to retrieve user's token");
return false;
}
}
// Request parameters to be replaced
String parameter = "{"
+ "\"org_id\":\"ORGANIZATION_ID\","
+ "\"datasets\":[\"DATASET_ID\"]"
+ "}";
if(organizationId != null && !organizationId.isEmpty() && datasetId != null && !datasetId.isEmpty()){
// replace with right data
parameter = parameter.replace("ORGANIZATION_ID", organizationId);
parameter = parameter.replace("DATASET_ID", datasetId);
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
if(priv){
try {
HttpPost request = new HttpPost(CKAN_CATALOGUE_URL + pathSetPrivate);
request.addHeader("Authorization", token);
StringEntity params = new StringEntity(parameter);
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
logger.debug("[PRIVATE]Response code is " + response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase());
if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
return true;
}catch (Exception ex) {
logger.error("Error while trying to set private the dataset " + ex);
}
}else
{
try {
HttpPost request = new HttpPost(CKAN_CATALOGUE_URL + pathSetPublic);
StringEntity params =new StringEntity(parameter);
request.addHeader("Authorization", token);
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
logger.debug("[PUBLIC]Response code is " + response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase());
if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
return true;
}catch (Exception ex) {
logger.error("Error while trying to set public the dataset " + ex);
}
}
}
return false;
}
}