From 2e63bc3455ade98eb2f75b55ecdff7700ca14e4f Mon Sep 17 00:00:00 2001 From: Costantino Perciante Date: Tue, 7 Jun 2016 14:00:05 +0000 Subject: [PATCH] First import git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-catalogue/ckan-util-library@129006 82a268e6-3cf1-43bd-a215-b396298e98cf --- .classpath | 27 ++ .project | 36 ++ .settings/org.eclipse.core.resources.prefs | 4 + .settings/org.eclipse.jdt.core.prefs | 8 + .settings/org.eclipse.m2e.core.prefs | 4 + .settings/org.eclipse.wst.common.component | 5 + ....eclipse.wst.common.project.facet.core.xml | 5 + .settings/org.eclipse.wst.validation.prefs | 2 + distro/LICENSE | 1 + distro/README | 62 ++++ distro/changelog.xml | 5 + distro/descriptor.xml | 31 ++ distro/profile.xml | 25 ++ pom.xml | 187 ++++++++++ .../ckanutillibrary/CKanRunningCluster.java | 169 +++++++++ .../ckanutillibrary/CKanUtilsFactory.java | 80 +++++ .../ckanutillibrary/CKanUtilsImpl.java | 322 ++++++++++++++++++ .../ckanutillibrary/CKanUtilsInterface.java | 73 ++++ .../NoCKanRuntimeResourceException.java | 24 ++ .../exceptions/ServiceEndPointException.java | 21 ++ .../TooManyRunningClustersException.java | 22 ++ .../models/CKanUserWrapper.java | 134 ++++++++ .../models/ROLES_IN_ORGANIZATION.java | 11 + .../ckanutillibrary/models/STATE.java | 10 + .../ckanutillibrary/TestCKanLib.java | 92 +++++ target/profile.xml | 25 ++ 26 files changed, 1385 insertions(+) create mode 100644 .classpath create mode 100644 .project create mode 100644 .settings/org.eclipse.core.resources.prefs create mode 100644 .settings/org.eclipse.jdt.core.prefs create mode 100644 .settings/org.eclipse.m2e.core.prefs create mode 100644 .settings/org.eclipse.wst.common.component create mode 100644 .settings/org.eclipse.wst.common.project.facet.core.xml create mode 100644 .settings/org.eclipse.wst.validation.prefs create mode 100644 distro/LICENSE create mode 100644 distro/README create mode 100644 distro/changelog.xml create mode 100644 distro/descriptor.xml create mode 100644 distro/profile.xml create mode 100644 pom.xml create mode 100644 src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanRunningCluster.java create mode 100644 src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsFactory.java create mode 100644 src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsImpl.java create mode 100644 src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsInterface.java create mode 100644 src/main/java/org/gcube/datacatalogue/ckanutillibrary/exceptions/NoCKanRuntimeResourceException.java create mode 100644 src/main/java/org/gcube/datacatalogue/ckanutillibrary/exceptions/ServiceEndPointException.java create mode 100644 src/main/java/org/gcube/datacatalogue/ckanutillibrary/exceptions/TooManyRunningClustersException.java create mode 100644 src/main/java/org/gcube/datacatalogue/ckanutillibrary/models/CKanUserWrapper.java create mode 100644 src/main/java/org/gcube/datacatalogue/ckanutillibrary/models/ROLES_IN_ORGANIZATION.java create mode 100644 src/main/java/org/gcube/datacatalogue/ckanutillibrary/models/STATE.java create mode 100644 src/test/java/org/gcube/datacatalogue/ckanutillibrary/TestCKanLib.java create mode 100644 target/profile.xml diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..5cca4e3 --- /dev/null +++ b/.classpath @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..7d02ff7 --- /dev/null +++ b/.project @@ -0,0 +1,36 @@ + + + ckan-util-library + + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..f9fe345 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/test/java=UTF-8 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..443e085 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..6bb5ced --- /dev/null +++ b/.settings/org.eclipse.wst.common.component @@ -0,0 +1,5 @@ + + + + + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..1b22d70 --- /dev/null +++ b/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/.settings/org.eclipse.wst.validation.prefs b/.settings/org.eclipse.wst.validation.prefs new file mode 100644 index 0000000..04cad8c --- /dev/null +++ b/.settings/org.eclipse.wst.validation.prefs @@ -0,0 +1,2 @@ +disabled=06target +eclipse.preferences.version=1 diff --git a/distro/LICENSE b/distro/LICENSE new file mode 100644 index 0000000..2d9616a --- /dev/null +++ b/distro/LICENSE @@ -0,0 +1 @@ +${gcube.license} \ No newline at end of file diff --git a/distro/README b/distro/README new file mode 100644 index 0000000..38d5603 --- /dev/null +++ b/distro/README @@ -0,0 +1,62 @@ +The gCube System - ${name} +-------------------------------------------------- + +${description} + + +${gcube.description} + +${gcube.funding} + + +Version +-------------------------------------------------- + +${version} (${buildDate}) + +Please see the file named "changelog.xml" in this directory for the release notes. + + +Authors +-------------------------------------------------- + +* Costantino Perciante (costantino.perciante@isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy). + +Maintainers +----------- + +* Costantino Perciante (costantino.perciante@isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy). + +Download information +-------------------------------------------------- + +Source code is available from SVN: + ${scm.url} + +Binaries can be downloaded from the gCube website: + ${gcube.website} + + +Installation +-------------------------------------------------- + +Installation documentation is available on-line in the gCube Wiki: + ${gcube.wikiRoot} + +Documentation +-------------------------------------------------- + +Documentation is available on-line in the gCube Wiki: + ${gcube.wikiRoot} + +Support +-------------------------------------------------- + +Bugs and support requests can be reported in the gCube issue tracking tool: + ${gcube.issueTracking} + + +Licensing +-------------------------------------------------- + +This software is licensed under the terms you may find in the file named "LICENSE" in this directory. \ No newline at end of file diff --git a/distro/changelog.xml b/distro/changelog.xml new file mode 100644 index 0000000..33d0290 --- /dev/null +++ b/distro/changelog.xml @@ -0,0 +1,5 @@ + + + First Release + + diff --git a/distro/descriptor.xml b/distro/descriptor.xml new file mode 100644 index 0000000..b3f5628 --- /dev/null +++ b/distro/descriptor.xml @@ -0,0 +1,31 @@ + + servicearchive + + tar.gz + + / + + + ${distroDirectory} + / + true + + README + LICENSE + changelog.xml + profile.xml + + 755 + true + + + + + target/${build.finalName}.${project.packaging} + /${artifactId} + + + \ No newline at end of file diff --git a/distro/profile.xml b/distro/profile.xml new file mode 100644 index 0000000..19466d1 --- /dev/null +++ b/distro/profile.xml @@ -0,0 +1,25 @@ + + + + Service + + ${Description} + DataAccess + ${artifactId} + ${version} + + + ${artifactId} + ${version} + + ${groupId} + ${artifactId} + ${version} + + + target/${build.finalName}.jar + + + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..8ad54d8 --- /dev/null +++ b/pom.xml @@ -0,0 +1,187 @@ + + 4.0.0 + + + maven-parent + org.gcube.tools + 1.0.0 + + + org.gcube.data-catalogue + ckan-util-library + 1.0.0-SNAPSHOT + jar + + CKan utility library + + Utility library to retrieve users information, organizations information and so on from the ckan d4science database. + + + + distro + 1.7 + 1.7 + 0.4.2 + 9.4.1208.jre7 + UTF-8 + UTF-8 + + + + + org.gcube.distribution + maven-portal-bom + LATEST + pom + import + + + + + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-simple + 1.6.4 + + + org.postgresql + postgresql + ${postgresVersion} + + + + eu.trentorise.opendata + jackan + ${jackanVersion} + compile + + + junit + junit + 4.8 + test + + + org.gcube.common.portal + portal-manager + provided + + + org.gcube.resources.discovery + ic-client + provided + + + org.gcube.core + common-encryption + provided + + + org.gcube.core + common-scope-maps + provided + + + + + + + + src/main/java + + **/*.* + + + + + + maven-compiler-plugin + + 1.7 + 1.7 + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + test-jar + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + true + + + + org.apache.maven.plugins + maven-resources-plugin + 2.5 + + + copy-profile + install + + copy-resources + + + target + + + ${distroDirectory} + true + + profile.xml + + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.2 + + + ${distroDirectory}/descriptor.xml + + + + fully.qualified.MainClass + + + + + + + + + servicearchive + install + + single + + + + + + + diff --git a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanRunningCluster.java b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanRunningCluster.java new file mode 100644 index 0000000..5348f0f --- /dev/null +++ b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanRunningCluster.java @@ -0,0 +1,169 @@ +package org.gcube.datacatalogue.ckanutillibrary; + +import static org.gcube.resources.discovery.icclient.ICFactory.clientFor; +import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.gcube.common.portal.PortalContext; +import org.gcube.common.resources.gcore.ServiceEndpoint; +import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.datacatalogue.ckanutillibrary.exceptions.NoCKanRuntimeResourceException; +import org.gcube.datacatalogue.ckanutillibrary.exceptions.ServiceEndPointException; +import org.gcube.datacatalogue.ckanutillibrary.exceptions.TooManyRunningClustersException; +import org.gcube.resources.discovery.client.api.DiscoveryClient; +import org.gcube.resources.discovery.client.queries.api.SimpleQuery; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Retrieve ckan running instance information in the infrastructure. + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class CKanRunningCluster { + + //logger + private static final Logger logger = LoggerFactory.getLogger(CKanRunningCluster.class); + + //properties + private final static String RUNTIME_RESOURCE_NAME = "CKanDatabase"; + private final static String PLATFORM_NAME = "postgres"; + + // retrieved data + private List hosts = new ArrayList(); + private List ports = new ArrayList(); + private String dbName; + private String dbUser; + private String dbPassword; + + public CKanRunningCluster(String infrastructure) throws Exception{ + + try { + + List resources = getConfigurationFromIS(infrastructure); + + if (resources.size() > 1) { + logger.error("Too many Runtime Resource having name " + RUNTIME_RESOURCE_NAME +" in this scope"); + throw new TooManyRunningClustersException("There exist more than 1 Runtime Resource in this scope having name " + + RUNTIME_RESOURCE_NAME + " and Platform " + PLATFORM_NAME + ". Only one allowed per infrasrtucture."); + } + else if (resources.size() == 0){ + logger.error("There is no Runtime Resource having name " + RUNTIME_RESOURCE_NAME +" and Platform " + PLATFORM_NAME + " in this scope."); + throw new NoCKanRuntimeResourceException(); + } + else { + + try{ + + logger.debug(resources.toString()); + for (ServiceEndpoint res : resources) { + + Iterator accessPointIterator = res.profile().accessPoints().iterator(); + + while (accessPointIterator.hasNext()) { + ServiceEndpoint.AccessPoint accessPoint = (ServiceEndpoint.AccessPoint) accessPointIterator + .next(); + + // add this host + hosts.add(accessPoint.address().split(":")[0]); + + // save the port + int port = Integer.parseInt(accessPoint.address().split(":")[1]); + ports.add(port); + + // save the name of the cluster (this should be unique) + dbName = accessPoint.name(); + + // save user and password + dbPassword = accessPoint.password(); + dbUser = accessPoint.username(); + + break; + + } + } + }catch(Exception e ){ + + logger.error(e.toString()); + throw new ServiceEndPointException(); + } + } + } catch (Exception e) { + logger.error(e.toString()); + throw e; + } + + } + + /** + * Retrieve endpoints information from IS + * @return list of endpoints for ckan + * @throws Exception + */ + private List getConfigurationFromIS(String infrastructure) throws Exception{ + + String scope = ""; + if(infrastructure != null && !infrastructure.isEmpty()) + scope += infrastructure; + else{ + + PortalContext context = PortalContext.getConfiguration(); + scope += context.getInfrastructureName(); + + } + + String currScope = ScopeProvider.instance.get(); + ScopeProvider.instance.set(scope); + SimpleQuery query = queryFor(ServiceEndpoint.class); + query.addCondition("$resource/Profile/Name/text() eq '"+ RUNTIME_RESOURCE_NAME +"'"); + query.addCondition("$resource/Profile/Platform/Name/text() eq '"+ PLATFORM_NAME +"'"); + DiscoveryClient client = clientFor(ServiceEndpoint.class); + List toReturn = client.submit(query); + ScopeProvider.instance.set(currScope); + return toReturn; + + } + + /** + * Get the hosts for such resource. + * @return + */ + public List getHosts() { + return hosts; + } + + /** + * Get the ports for such resource. + * @return + */ + public List getPorts() { + return ports; + } + + /** + * Get the database name. + * @return + */ + public String getDataBaseName() { + return dbName; + } + + /** + * Get the database's user. + * @return + */ + public String getDataBaseUser() { + return dbUser; + } + + /** + * Get the database's password. + * @return + */ + public String getDataBasePassword() { + return dbPassword; + } +} diff --git a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsFactory.java b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsFactory.java new file mode 100644 index 0000000..540fcc7 --- /dev/null +++ b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsFactory.java @@ -0,0 +1,80 @@ +package org.gcube.datacatalogue.ckanutillibrary; + +import java.util.HashMap; +import java.util.Map; + +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 + */ + private static Map instanceForScopes; + + /** + * this object singleton instance + */ + private static CKanUtilsFactory factoryInstance = new CKanUtilsFactory(); + + /** + * private constructor + */ + private CKanUtilsFactory(){ + + logger.debug("Instanciating factory"); + instanceForScopes = new HashMap(); + + } + + /** + * 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); + + synchronized (instanceForScopes) { + + if(instanceForScopes.containsKey(scope)){ + + logger.debug("Catalogue utils already cached, returning object"); + return instanceForScopes.get(scope); + + } + else{ + + logger.debug("Instanciating utils for this scope"); + CKanUtilsImpl utilsForScope = new CKanUtilsImpl("/gcube"); + + // save into the map + instanceForScopes.put(scope, utilsForScope); + + return utilsForScope; + + } + } + } +} diff --git a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsImpl.java b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsImpl.java new file mode 100644 index 0000000..1fac079 --- /dev/null +++ b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsImpl.java @@ -0,0 +1,322 @@ +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.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.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 Integer CKAN_DB_PORT; + + // Connection to the db + private static Connection connection; + + public CKanUtilsImpl(String scope) throws Exception{ + + CKanRunningCluster runningInstance = new CKanRunningCluster(scope); + CKAN_CATALOGUE_URL = runningInstance.getHosts().get(0); + CKAN_DB_NAME = runningInstance.getDataBaseName(); + CKAN_DB_USER = runningInstance.getDataBaseUser(); + CKAN_DB_PASSWORD = StringEncrypter.getEncrypter().decrypt(runningInstance.getDataBasePassword(), scope); + CKAN_DB_PORT = runningInstance.getPorts().get(0); + + // create db connection + Class.forName("org.postgresql.Driver"); + connection = DriverManager.getConnection( + "jdbc:postgresql://" + CKAN_CATALOGUE_URL + ":" + CKAN_DB_PORT + "/" + CKAN_DB_NAME, CKAN_DB_USER, CKAN_DB_PASSWORD); + + } + + @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 getOrganizationsByUser(String username) { + + logger.debug("Requested organizations for user " + username); + List organizationIds = getOrganizationsIds(); + String userId = getUserIdByUsername(username); + + // list to return + List toReturn = new ArrayList(); + + // 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> getGroupsAndRolesByUser( + String username, List rolesToMatch) { + + logger.debug("Requested roles the user " + username + " has into its organizations"); + logger.debug("Roles to check are " + rolesToMatch); + Map> toReturn = new HashMap>(); + + try{ + + // get id from the user + String userId = getUserIdByUsername(username); + + // use the above method to require the list of user's organizations + List 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 rolesIntoOrg = new ArrayList(); + + 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 getOrganizationsIds(){ + logger.debug("Request organization ids"); + List toReturn = new ArrayList(); + + 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 getCatalogueUrl() { + return "https://" + CKAN_CATALOGUE_URL; + } + + @Override + public List getOrganizationsNamesByUser(String username) { + + List orgs = getOrganizationsByUser(username); + List orgsName = new ArrayList(); + 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 licenses = client.getLicenseList(); + + for (CkanLicense ckanLicense : licenses) { + if(ckanLicense.getTitle().equals(chosenLicense)) + return ckanLicense.getId(); + } + + return null; + } + + @Override + public List getLicenseTitles() { + logger.info("Request for CKAN licenses"); + + // get the url and the api key of the user + String ckanPortalUrl = getCatalogueUrl(); + List result = new ArrayList(); + + CkanClient client = new CkanClient(ckanPortalUrl); + + //retrieve the list of available licenses + List licenses = client.getLicenseList(); + + for (CkanLicense ckanLicense : licenses) { + + result.add(ckanLicense.getTitle()); + logger.debug("License is " + ckanLicense.getTitle() + " and id " + ckanLicense.getId()); + + } + + return result; + } +} diff --git a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsInterface.java b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsInterface.java new file mode 100644 index 0000000..9c53e8c --- /dev/null +++ b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/CKanUtilsInterface.java @@ -0,0 +1,73 @@ +package org.gcube.datacatalogue.ckanutillibrary; + +import java.util.List; +import java.util.Map; + +import org.gcube.datacatalogue.ckanutillibrary.models.CKanUserWrapper; +import org.gcube.datacatalogue.ckanutillibrary.models.ROLES_IN_ORGANIZATION; + +import eu.trentorise.opendata.jackan.model.CkanOrganization; + +/** + * This is the ckan-util-library interface that shows the utility methods. + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public interface CKanUtilsInterface { + + /** + * Retrieve the API_KEY given the username . + * @param username + * @return an API_KEY string + */ + public String getApiKeyFromUser(String username); + + /** + * Retrieve the user given the API_KEY (the user is retrieved if it is active). + * @param username + * @return an API_KEY string + */ + public CKanUserWrapper getUserFromApiKey(String apiKey); + + /** + * Returns the list of organizations to whom the user belongs. + * @param username + * @return a list of organizations + */ + public List getOrganizationsByUser(String username); + + /** + * Returns the list of organizations' names to whom the user belongs. + * @param username + * @return a list of organizations + */ + public List getOrganizationsNamesByUser(String username); + + /** + * Given a username and a list of roles to be matched, find the organizations to who the user + * belongs and the role(s) he has in them. + * @param username + * @param rolesToMatch + * @return + */ + public Map> getGroupsAndRolesByUser(String username, List rolesToMatch); + + /** + * Return the ckan catalogue url in this scope. + * @return + */ + public String getCatalogueUrl(); + + /** + * Get the list of licenses' titles. + * @return + */ + public List getLicenseTitles(); + + /** + * Finds the id associated to the chosen license + * @param chosenLicense + * @return + */ + public String findLicenseIdByLicense(String chosenLicense); + +} diff --git a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/exceptions/NoCKanRuntimeResourceException.java b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/exceptions/NoCKanRuntimeResourceException.java new file mode 100644 index 0000000..af39a8f --- /dev/null +++ b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/exceptions/NoCKanRuntimeResourceException.java @@ -0,0 +1,24 @@ +package org.gcube.datacatalogue.ckanutillibrary.exceptions; + +/** + * No elasticsearch cluster in the infrastructure found exception. + * @author Costantino Perciante at ISTI-CNR + * (costantino.perciante@isti.cnr.it) + * + */ +public class NoCKanRuntimeResourceException extends Exception { + + private static final long serialVersionUID = -40748130477807648L; + + private static final String DEFAULT_MESSAGE = "No CKan catalogue instance for this scope!"; + + public NoCKanRuntimeResourceException(){ + super(DEFAULT_MESSAGE); + } + + public NoCKanRuntimeResourceException(String message) { + super(message); + } + + +} diff --git a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/exceptions/ServiceEndPointException.java b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/exceptions/ServiceEndPointException.java new file mode 100644 index 0000000..a15e6a4 --- /dev/null +++ b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/exceptions/ServiceEndPointException.java @@ -0,0 +1,21 @@ +package org.gcube.datacatalogue.ckanutillibrary.exceptions; + +/** + * Exception thrown when it is not possible retrieve information from the ServiceEndpoint + * related to ElasticSearch + * @author Costantino Perciante at ISTI-CNR + * (costantino.perciante@isti.cnr.it) + * + */ +public class ServiceEndPointException extends Exception { + + private static final long serialVersionUID = 7057074369001221035L; + private static final String DEFAULT_MESSAGE = "Unable to retrieve information from CKan endpoint!"; + + public ServiceEndPointException(){ + super(DEFAULT_MESSAGE); + } + public ServiceEndPointException(String string) { + super(string); + } +} diff --git a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/exceptions/TooManyRunningClustersException.java b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/exceptions/TooManyRunningClustersException.java new file mode 100644 index 0000000..57901cc --- /dev/null +++ b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/exceptions/TooManyRunningClustersException.java @@ -0,0 +1,22 @@ +package org.gcube.datacatalogue.ckanutillibrary.exceptions; + +/** + * Too many clusters in this scope exception. + * @author Costantino Perciante at ISTI-CNR + * (costantino.perciante@isti.cnr.it) + * + */ +public class TooManyRunningClustersException extends Exception { + + private static final long serialVersionUID = -7847493730006647045L; + private static final String DEFAULT_MESSAGE = "Too many CKan data catalague instances for this scope!"; + + public TooManyRunningClustersException(){ + super(DEFAULT_MESSAGE); + } + + public TooManyRunningClustersException(String message) { + super(message); + } + +} diff --git a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/models/CKanUserWrapper.java b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/models/CKanUserWrapper.java new file mode 100644 index 0000000..8e23343 --- /dev/null +++ b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/models/CKanUserWrapper.java @@ -0,0 +1,134 @@ +package org.gcube.datacatalogue.ckanutillibrary.models; + +import java.io.Serializable; + +/** + * A CKan user. + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +public class CKanUserWrapper implements Serializable{ + + private static final long serialVersionUID = 6264706263035722775L; + + private String id; + private String name; + private String apiKey; + private long creationTimestamp; + private String about; + private String openId; + private String fullName; + private String email; + private boolean isAdmin; + + + public CKanUserWrapper() { + super(); + } + + /** Create a ckan user object. + * @param id + * @param name + * @param apiKey + * @param creationTimestamp + * @param about + * @param openId + * @param fullName + * @param email + * @param isAdmin + */ + public CKanUserWrapper(String id, String name, String apiKey, + long creationTimestamp, String about, String openId, + String fullName, String email, boolean isAdmin) { + super(); + this.id = id; + this.name = name; + this.apiKey = apiKey; + this.creationTimestamp = creationTimestamp; + this.about = about; + this.openId = openId; + this.fullName = fullName; + this.email = email; + this.isAdmin = isAdmin; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public long getCreationTimestamp() { + return creationTimestamp; + } + + public void setCreationTimestamp(long creationTimestamp) { + this.creationTimestamp = creationTimestamp; + } + + public String getAbout() { + return about; + } + + public void setAbout(String about) { + this.about = about; + } + + public String getOpenId() { + return openId; + } + + public void setOpenId(String openId) { + this.openId = openId; + } + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public boolean isAdmin() { + return isAdmin; + } + + public void setAdmin(boolean isAdmin) { + this.isAdmin = isAdmin; + } + + @Override + public String toString() { + return "CKanUserExtended [id=" + id + ", name=" + name + ", apiKey=" + apiKey + + ", creationTimestamp=" + creationTimestamp + ", about=" + + about + ", openId=" + openId + ", fullName=" + fullName + + ", email=" + email + ", isAdmin=" + isAdmin + "]"; + } + +} diff --git a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/models/ROLES_IN_ORGANIZATION.java b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/models/ROLES_IN_ORGANIZATION.java new file mode 100644 index 0000000..bda23be --- /dev/null +++ b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/models/ROLES_IN_ORGANIZATION.java @@ -0,0 +1,11 @@ +package org.gcube.datacatalogue.ckanutillibrary.models; + +/** + * Roles that user can have into the group table + * @author Costantino Perciante at ISTI-CNR + * (costantino.perciante@isti.cnr.it) + * + */ +public enum ROLES_IN_ORGANIZATION{ + editor, admin, member +} \ No newline at end of file diff --git a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/models/STATE.java b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/models/STATE.java new file mode 100644 index 0000000..3a9c743 --- /dev/null +++ b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/models/STATE.java @@ -0,0 +1,10 @@ +package org.gcube.datacatalogue.ckanutillibrary.models; + +/** + * The current state of this group/user + * @author Costantino Perciante at ISTI-CNR + * (costantino.perciante@isti.cnr.it) + */ +public enum STATE{ + deleted, active +} \ No newline at end of file diff --git a/src/test/java/org/gcube/datacatalogue/ckanutillibrary/TestCKanLib.java b/src/test/java/org/gcube/datacatalogue/ckanutillibrary/TestCKanLib.java new file mode 100644 index 0000000..d7fe512 --- /dev/null +++ b/src/test/java/org/gcube/datacatalogue/ckanutillibrary/TestCKanLib.java @@ -0,0 +1,92 @@ +package org.gcube.datacatalogue.ckanutillibrary; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.gcube.datacatalogue.ckanutillibrary.CKanUtilsFactory; +import org.gcube.datacatalogue.ckanutillibrary.CKanUtilsImpl; +import org.gcube.datacatalogue.ckanutillibrary.models.CKanUserWrapper; +import org.gcube.datacatalogue.ckanutillibrary.models.ROLES_IN_ORGANIZATION; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import eu.trentorise.opendata.jackan.model.CkanOrganization; + +public class TestCKanLib { + + private static final Logger logger = LoggerFactory.getLogger(TestCKanLib.class); + + CKanUtilsImpl instance; + + //@Before + public void before() throws Exception{ + + instance = new CKanUtilsImpl("/gcube"); + + } + + //@Test + public void testgetApiKeyFromUser() { + + logger.debug("Testing getApiKeyFromUser"); + + String username = "francescomangiacrapa"; + String key = instance.getApiKeyFromUser(username); + + System.out.println("key for " + username + " is " + key); + } + + //@Test + public void testgetUserFromApiKey() { + + logger.debug("Testing getApiKeyFromUser"); + + String key = "put-your-key-here"; + CKanUserWrapper user = instance.getUserFromApiKey(key); + + System.out.println("user for " + key + " is " + user); + } + + //@Test + public void getOrganizationsByUser() { + + System.out.println("Testing getOrganizationsByUser"); + + String username = "francescomangiacrapa"; + List organizations = instance.getOrganizationsByUser(username); + + System.out.println("organizations for user " + username + " are: "); + + for (CkanOrganization ckanOrganization : organizations) { + System.out.println("-" + ckanOrganization.getName()); + } + } + + //@Test + public void getGroupsAndRolesByUser() { + + logger.debug("Testing getGroupsAndRolesByUser"); + + String username = "francescomangiacrapa"; + List rolesToMatch = new ArrayList(); + rolesToMatch.add(ROLES_IN_ORGANIZATION.admin); + rolesToMatch.add(ROLES_IN_ORGANIZATION.member); + rolesToMatch.add(ROLES_IN_ORGANIZATION.editor); + Map> map = instance.getGroupsAndRolesByUser(username, rolesToMatch); + + 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()); + + + } + +} diff --git a/target/profile.xml b/target/profile.xml new file mode 100644 index 0000000..3d41792 --- /dev/null +++ b/target/profile.xml @@ -0,0 +1,25 @@ + + + + Service + + Utility library to retrieve users information, organizations information and so on from the ckan d4science database. + DataAccess + ckan-util-library + 1.0.0-SNAPSHOT + + + ckan-util-library + 1.0.0-SNAPSHOT + + org.gcube.data-catalogue + ckan-util-library + 1.0.0-SNAPSHOT + + + target/ckan-util-library-1.0.0-SNAPSHOT.jar + + + + +