2016-06-07 16:00:05 +02:00
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 ;
2016-06-13 12:07:41 +02:00
import org.gcube.common.scope.api.ScopeProvider ;
2016-06-07 16:00:05 +02:00
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 ;
2016-06-10 16:26:01 +02:00
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 ;
2016-06-07 16:00:05 +02:00
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 ;
2016-06-10 14:15:38 +02:00
private String CKAN_DB_URL ;
2016-06-07 16:00:05 +02:00
private Integer CKAN_DB_PORT ;
// Connection to the db
private static Connection connection ;
public CKanUtilsImpl ( String scope ) throws Exception {
2016-06-13 12:07:41 +02:00
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 ( ) ) ;
2016-06-13 14:15:06 +02:00
logger . debug ( " Plain password first 3 chars are " + CKAN_DB_PASSWORD . substring ( 0 , 2 ) ) ;
2016-06-13 12:29:21 +02:00
// for next versions TODO
2016-06-13 12:07:41 +02:00
//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 ) {
2016-06-13 14:15:06 +02:00
logger . error ( " Error while discovering ckan information in the infrastructure " , e ) ;
2016-06-13 12:07:41 +02:00
} finally {
ScopeProvider . instance . reset ( ) ;
}
2016-06-07 16:00:05 +02:00
}
@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 ( ) ;
}
2016-06-10 14:15:38 +02:00
@Override
public String getCKANDBUrl ( ) {
return CKAN_DB_URL ;
}
2016-06-10 16:26:01 +02:00
2016-06-07 16:00:05 +02:00
@Override
public String getCatalogueUrl ( ) {
2016-06-10 14:15:38 +02:00
return CKAN_CATALOGUE_URL ;
2016-06-07 16:00:05 +02:00
}
@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 ;
2016-06-08 18:31:25 +02:00
2016-06-07 16:00:05 +02:00
}
@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 ( ) ) ;
}
2016-06-08 18:31:25 +02:00
2016-06-07 16:00:05 +02:00
return result ;
}
2016-06-10 14:15:38 +02:00
2016-06-10 16:26:01 +02:00
@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 ( ) ) ;
2016-06-13 12:07:41 +02:00
2016-06-10 16:26:01 +02:00
if ( response . getStatusLine ( ) . getStatusCode ( ) = = HttpStatus . SC_OK )
return true ;
2016-06-13 12:07:41 +02:00
2016-06-10 16:26:01 +02:00
} catch ( Exception ex ) {
logger . error ( " Error while trying to set public the dataset " + ex ) ;
}
}
}
return false ;
}
2016-06-07 16:00:05 +02:00
}