From 2edc222f6e56cbd02256849ab017334cef124137 Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Tue, 15 Feb 2022 09:59:02 +0100 Subject: [PATCH] Implementing Configuration Management refs #22658 --- CHANGELOG.md | 3 +- pom.xml | 4 + .../GCoreISConfigurationProxy.java | 307 ++++++++++++++++++ .../org/gcube/gcat/persistence/ckan/CKAN.java | 2 +- .../gcat/persistence/ckan/CKANInstance.java | 297 ----------------- .../gcat/persistence/ckan/CKANPackage.java | 40 +-- .../persistence/ckan/CKANPackageTrash.java | 7 +- .../gcat/persistence/ckan/CKANUtility.java | 2 +- .../ckan/CatalogueConfigurationFactory.java | 60 ++++ .../org/gcube/gcat/rest/Configuration.java | 268 +++++++++++++++ .../org/gcube/gcat/social/SocialPost.java | 5 +- .../GCoreISConfigurationProxyTest.java | 102 ++++++ .../persistence/ckan/CKANInstanceTest.java | 21 ++ .../persistence/ckan/CKANPackageTest.java | 86 +---- 14 files changed, 792 insertions(+), 412 deletions(-) create mode 100644 src/main/java/org/gcube/gcat/configuration/GCoreISConfigurationProxy.java delete mode 100644 src/main/java/org/gcube/gcat/persistence/ckan/CKANInstance.java create mode 100644 src/main/java/org/gcube/gcat/persistence/ckan/CatalogueConfigurationFactory.java create mode 100644 src/main/java/org/gcube/gcat/rest/Configuration.java create mode 100644 src/test/java/org/gcube/gcat/configuration/GCoreISConfigurationProxyTest.java create mode 100644 src/test/java/org/gcube/gcat/persistence/ckan/CKANInstanceTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 247e474..35ec6fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [v2.2.0-SNAPSHOT] -- Switched gcat credentials to new IAM authz [#21628][#22727] +- Switched gcat credentials to new IAM authz [#21628][#22727] +- Added support to manage configurations ## [v2.1.0] diff --git a/pom.xml b/pom.xml index 8d07c60..5c23c2b 100644 --- a/pom.xml +++ b/pom.xml @@ -47,6 +47,10 @@ org.slf4j slf4j-api + + org.gcube.core + common-scope + org.gcube.data-catalogue gcat-api diff --git a/src/main/java/org/gcube/gcat/configuration/GCoreISConfigurationProxy.java b/src/main/java/org/gcube/gcat/configuration/GCoreISConfigurationProxy.java new file mode 100644 index 0000000..c5076d7 --- /dev/null +++ b/src/main/java/org/gcube/gcat/configuration/GCoreISConfigurationProxy.java @@ -0,0 +1,307 @@ +package org.gcube.gcat.configuration; + +import static org.gcube.resources.discovery.icclient.ICFactory.clientFor; +import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.WebApplicationException; + +import org.gcube.com.fasterxml.jackson.databind.JsonNode; +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; +import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode; +import org.gcube.common.encryption.encrypter.StringEncrypter; +import org.gcube.common.resources.gcore.GenericResource; +import org.gcube.common.resources.gcore.ServiceEndpoint; +import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; +import org.gcube.common.resources.gcore.ServiceEndpoint.Property; +import org.gcube.gcat.api.configuration.CatalogueConfiguration; +import org.gcube.informationsystem.publisher.RegistryPublisher; +import org.gcube.informationsystem.publisher.RegistryPublisherFactory; +import org.gcube.resources.discovery.client.api.DiscoveryClient; +import org.gcube.resources.discovery.client.queries.api.SimpleQuery; +import org.gcube.resources.discovery.icclient.ICFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GCoreISConfigurationProxy { + + private static final Logger logger = LoggerFactory.getLogger(GCoreISConfigurationProxy.class); + + // property to retrieve the master service endpoint into the /root scope + private final static String IS_MASTER_ROOT_KEY_PROPERTY = "IS_ROOT_MASTER"; // true, false.. missing means false as + + private final static String API_KEY_PROPERTY = "API_KEY"; + private final static String SOCIAL_POST = "SOCIAL_POST"; + private final static String ALERT_USERS_ON_POST_CREATION = "ALERT_USERS_ON_POST_CREATION"; + private final static String MODERATION_ENABLED_KEY = "MODERATION_ENABLED"; + + // CKAN Instance info + private final static String RUNTIME_CATALOGUE_RESOURCE_NAME = "CKanDataCatalogue"; + private final static String PLATFORM_CATALOGUE_NAME = "Tomcat"; + + protected final String context; + protected CatalogueConfiguration catalogueConfiguration; + + public GCoreISConfigurationProxy(String context) { + this.context = context; + } + + public GCoreISConfigurationProxy(String context, CatalogueConfiguration catalogueConfiguration) { + this(context); + this.catalogueConfiguration = catalogueConfiguration; + + } + + public CatalogueConfiguration getCatalogueConfiguration() { + if (catalogueConfiguration == null) { + loadFromIS(); + } + return catalogueConfiguration; + } + + protected CatalogueConfiguration loadFromIS() { + try { + catalogueConfiguration = new CatalogueConfiguration(context); + + ServiceEndpoint serviceEndpoint = getServiceEndpoint(); + if (serviceEndpoint == null) { + throw new InternalServerErrorException("No CKAN configuration on IS"); + } + + catalogueConfiguration.setID(serviceEndpoint.id()); + + Iterator accessPointIterator = serviceEndpoint.profile().accessPoints().iterator(); + while (accessPointIterator.hasNext()) { + AccessPoint accessPoint = accessPointIterator.next(); + + // add this host + String ckanURL = accessPoint.address(); + catalogueConfiguration.setCkanURL(ckanURL); + + // retrieve sys admin token + String sysAdminToken = accessPoint.propertyMap().get(API_KEY_PROPERTY).value(); + sysAdminToken = StringEncrypter.getEncrypter().decrypt(sysAdminToken); + catalogueConfiguration.setSysAdminToken(sysAdminToken); + + // retrieve option to check if the social post has to be made + Boolean socialPostEnabled = true; + if (accessPoint.propertyMap().containsKey(SOCIAL_POST)) { + if (accessPoint.propertyMap().get(SOCIAL_POST).value().trim().equalsIgnoreCase("false")) { + socialPostEnabled = false; + } + } + catalogueConfiguration.setSocialPostEnabled(socialPostEnabled); + + // retrieve option for user alert + boolean notificationToUsersEnabled = false; // default is false + if (accessPoint.propertyMap().containsKey(ALERT_USERS_ON_POST_CREATION)) { + if (accessPoint.propertyMap().get(ALERT_USERS_ON_POST_CREATION).value().trim() + .equalsIgnoreCase("true")) { + notificationToUsersEnabled = true; + } + } + catalogueConfiguration.setNotificationToUsersEnabled(notificationToUsersEnabled); + + boolean moderationEnabled = false; // default is false + if (accessPoint.propertyMap().containsKey(MODERATION_ENABLED_KEY)) { + if (accessPoint.propertyMap().get(MODERATION_ENABLED_KEY).value().trim().equalsIgnoreCase("true")) { + moderationEnabled = true; + } + } + catalogueConfiguration.setModerationEnabled(moderationEnabled); + + } + + Set supportedOrganizations = getSupportedOrganizationsFromIS(); + if (supportedOrganizations != null) { + catalogueConfiguration.setSupportedOrganizations(supportedOrganizations); + } + + } catch (WebApplicationException e) { + throw e; + } catch (Exception e) { + throw new InternalServerErrorException("Error while getting configuration on IS", e); + } + + return catalogueConfiguration; + } + + /** + * Retrieve endpoints information from IS for DataCatalogue URL + * + * @return list of endpoints for ckan data catalogue + * @throws Exception + */ + private List getServiceEndpoints() { + 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 client = clientFor(ServiceEndpoint.class); + List serviceEndpoints = client.submit(query); + return serviceEndpoints; + } + + private ServiceEndpoint getServiceEndpoint() { + List serviceEndpoints = getServiceEndpoints(); + + if (serviceEndpoints.size() == 0) { + logger.error("There is no {} having name {} and Platform {} in this context.", + ServiceEndpoint.class.getSimpleName(), RUNTIME_CATALOGUE_RESOURCE_NAME, PLATFORM_CATALOGUE_NAME); + return null; + } + + ServiceEndpoint serviceEndpoint = null; + + if (serviceEndpoints.size() > 1) { + logger.info("Too many {} having name {} in this context. Looking for the one that has the property {}", + ServiceEndpoint.class.getSimpleName(), RUNTIME_CATALOGUE_RESOURCE_NAME, + IS_MASTER_ROOT_KEY_PROPERTY); + + for (ServiceEndpoint se : serviceEndpoints) { + Iterator accessPointIterator = se.profile().accessPoints().iterator(); + while (accessPointIterator.hasNext()) { + ServiceEndpoint.AccessPoint accessPoint = accessPointIterator.next(); + + // get the is master property + Property entry = accessPoint.propertyMap().get(IS_MASTER_ROOT_KEY_PROPERTY); + String isMaster = entry != null ? entry.value() : null; + + if (isMaster == null || !isMaster.equals("true")) { + continue; + } + + // set this variable + serviceEndpoint = se; + break; + } + } + + // if none of them was master, throw an exception + if (serviceEndpoint == null) { + throw new InternalServerErrorException( + "Too many catalogue configuration on IS and no one with MASTER property"); + } + + } else { + serviceEndpoint = serviceEndpoints.get(0); + } + + return serviceEndpoint; + } + + public static final String GENERIC_RESOURCE_SECONDARY_TYPE_FOR_ORGANIZATIONS = "ApplicationProfile"; + public static final String GENERIC_RESOURCE_NAME_FOR_ORGANIZATIONS = "Supported CKAN Organizations"; + public static final String GENERIC_RESOURCE_CKAN_ORGANIZATIONS = "CKANOrganizations"; + + private List getGenericResources() { + SimpleQuery query = ICFactory.queryFor(GenericResource.class); + query.addCondition(String.format("$resource/Profile/SecondaryType/text() eq '%s'", + GENERIC_RESOURCE_SECONDARY_TYPE_FOR_ORGANIZATIONS)); + query.addCondition( + String.format("$resource/Profile/Name/text() eq '%s'", GENERIC_RESOURCE_NAME_FOR_ORGANIZATIONS)); + + DiscoveryClient client = ICFactory.clientFor(GenericResource.class); + List genericResources = client.submit(query); + return genericResources; + } + + protected Set getSupportedOrganizationsFromIS() { + List genericResources = getGenericResources(); + + if (genericResources == null || genericResources.size() == 0) { + logger.trace( + "{} with SecondaryType {} and Name %s not found. Item will be only be created in {} CKAN organization", + GenericResource.class.getSimpleName(), GENERIC_RESOURCE_SECONDARY_TYPE_FOR_ORGANIZATIONS, + GENERIC_RESOURCE_NAME_FOR_ORGANIZATIONS, CatalogueConfiguration.getOrganizationName(context)); + return null; + } + + if (genericResources.size() > 1) { + throw new InternalServerErrorException( + "To many generic resources to get supported organizations in context " + context); + } + + GenericResource genericResource = genericResources.get(0); + + try { + String body = genericResource.profile().body().getTextContent(); + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonNode = objectMapper.readTree(body); + ArrayNode array = (ArrayNode) jsonNode.get(GENERIC_RESOURCE_CKAN_ORGANIZATIONS); + Set supportedOrganizations = new HashSet<>(array.size()); + for (int i = 0; i < array.size(); i++) { + String o = array.get(i).asText(); + supportedOrganizations.add(o); + } + + logger.debug("Supported CKAN Organization for current Context ({}) are {}", context, + supportedOrganizations); + + return supportedOrganizations; + } catch (Exception e) { + + } + + return null; + } + + + public void delete() { + RegistryPublisher registryPublisher = RegistryPublisherFactory.create(); + + ServiceEndpoint serviceEndpoint = getServiceEndpoint(); + if(serviceEndpoint!=null) { + registryPublisher.remove(serviceEndpoint); + } + + List genericResources = getGenericResources(); + if(genericResources!=null) { + for(GenericResource genericResource : genericResources) { + registryPublisher.remove(genericResource); + } + } + } + + + protected ServiceEndpoint manageServiceEndpoint(ServiceEndpoint serviceEndpoint) { + + + return serviceEndpoint; + } + + public CatalogueConfiguration createOrUpdate() { + ServiceEndpoint serviceEndpoint = getServiceEndpoint(); + + RegistryPublisher registryPublisher = RegistryPublisherFactory.create(); + + if(serviceEndpoint!=null) { + // It's an update + String id = serviceEndpoint.id(); + if(catalogueConfiguration.getID().compareTo(id)!=0) { + catalogueConfiguration.setID(id); + } + serviceEndpoint = manageServiceEndpoint(serviceEndpoint); + registryPublisher.update(serviceEndpoint); + }else { + // It's a create + String id = catalogueConfiguration.getID(); + if(id==null || id.compareTo("")==0) { + id = UUID.randomUUID().toString(); + } + + serviceEndpoint = new ServiceEndpoint(); + serviceEndpoint = manageServiceEndpoint(serviceEndpoint); + serviceEndpoint.setId(id); + registryPublisher.create(serviceEndpoint); + } + + return catalogueConfiguration; + } + +} diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java index 32086ac..0585f34 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java @@ -234,7 +234,7 @@ public abstract class CKAN { protected GXHTTPStringRequest getGXHTTPStringRequest(String path, boolean post) throws UnsupportedEncodingException { - String catalogueURL = CKANInstance.getInstance().getCKANURL(); + String catalogueURL = CatalogueConfigurationFactory.getInstance().getCkanURL(); GXHTTPStringRequest gxhttpStringRequest = HTTPUtility.createGXHTTPStringRequest(catalogueURL, path, post); gxhttpStringRequest.isExternalCall(true); diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANInstance.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANInstance.java deleted file mode 100644 index 4c73654..0000000 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANInstance.java +++ /dev/null @@ -1,297 +0,0 @@ -package org.gcube.gcat.persistence.ckan; - -import static org.gcube.resources.discovery.icclient.ICFactory.clientFor; -import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.ws.rs.InternalServerErrorException; -import javax.ws.rs.WebApplicationException; - -import org.gcube.com.fasterxml.jackson.databind.JsonNode; -import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; -import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode; -import org.gcube.common.authorization.utils.manager.SecretManager; -import org.gcube.common.encryption.encrypter.StringEncrypter; -import org.gcube.common.resources.gcore.GenericResource; -import org.gcube.common.resources.gcore.ServiceEndpoint; -import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; -import org.gcube.common.resources.gcore.ServiceEndpoint.Property; -import org.gcube.common.scope.impl.ScopeBean; -import org.gcube.resources.discovery.client.api.DiscoveryClient; -import org.gcube.resources.discovery.client.queries.api.SimpleQuery; -import org.gcube.resources.discovery.icclient.ICFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author Luca Frosini (ISTI - CNR) - */ -public class CKANInstance { - - private static final Logger logger = LoggerFactory.getLogger(CKANInstance.class); - - // CKAN Instance info - private final static String RUNTIME_CATALOGUE_RESOURCE_NAME = "CKanDataCatalogue"; - private final static String PLATFORM_CATALOGUE_NAME = "Tomcat"; - - // property to retrieve the master service endpoint into the /root scope - private final static String IS_MASTER_ROOT_KEY_PROPERTY = "IS_ROOT_MASTER"; // true, false.. missing means false as well - - private final static String API_KEY_PROPERTY = "API_KEY"; - private final static String SOCIAL_POST = "SOCIAL_POST"; - private final static String ALERT_USERS_ON_POST_CREATION = "ALERT_USERS_ON_POST_CREATION"; - private final static String URL_RESOLVER = "URL_RESOLVER"; - private final static String MODERATION_ENABLED_KEY = "MODERATION_ENABLED"; - - private static final Map ckanInstancePerScope; - - protected String ckanURL; - protected String sysAdminToken; - protected boolean socialPostEnabled; - protected Boolean notificationToUsersEnabled; - protected String uriResolverURL; - - protected boolean moderationEnabled; - - protected final String currentContext; - protected final ScopeBean currentScopeBean; - - protected final String currentOrganizationName; - protected final Set supportedOrganizations; - - - static { - ckanInstancePerScope = new HashMap(); - } - - public static CKANInstance getInstance() { - String context = SecretManager.instance.get().getContext(); - CKANInstance ckanInstance = ckanInstancePerScope.get(context); - if(ckanInstance == null) { - ckanInstance = new CKANInstance(); - ckanInstance.getConfigurationFromIS(); - ckanInstancePerScope.put(context, ckanInstance); - } - return ckanInstance; - } - - - private CKANInstance() { - currentContext = SecretManager.instance.get().getContext(); - currentScopeBean = new ScopeBean(currentContext); - currentOrganizationName = CKANPackage.getOrganizationName(currentScopeBean); - supportedOrganizations = getSupportedOrganizationsFromIS(); - } - - /** - * Retrieve endpoints information from IS for DataCatalogue URL - * @return list of endpoints for ckan data catalogue - * @throws Exception - */ - private static List getServiceEndpoints() { - 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 client = clientFor(ServiceEndpoint.class); - List serviceEndpoints = client.submit(query); - if(serviceEndpoints.size() == 0) { - logger.error("There is no {} having name {} and Platform {} in this context.", - ServiceEndpoint.class.getSimpleName(), RUNTIME_CATALOGUE_RESOURCE_NAME, PLATFORM_CATALOGUE_NAME); - throw new InternalServerErrorException("No CKAN configuration on IS"); - } - return serviceEndpoints; - } - - private void getConfigurationFromIS() { - try { - List serviceEndpoints = getServiceEndpoints(); - ServiceEndpoint serviceEndpoint = null; - - if(serviceEndpoints.size() > 1) { - logger.info("Too many {} having name {} in this context. Looking for the one that has the property {}", - ServiceEndpoint.class.getSimpleName(), RUNTIME_CATALOGUE_RESOURCE_NAME, - IS_MASTER_ROOT_KEY_PROPERTY); - - for(ServiceEndpoint se : serviceEndpoints) { - Iterator accessPointIterator = se.profile().accessPoints().iterator(); - while(accessPointIterator.hasNext()) { - ServiceEndpoint.AccessPoint accessPoint = accessPointIterator.next(); - - // get the is master property - Property entry = accessPoint.propertyMap().get(IS_MASTER_ROOT_KEY_PROPERTY); - String isMaster = entry != null ? entry.value() : null; - - if(isMaster == null || !isMaster.equals("true")) { - continue; - } - - // set this variable - serviceEndpoint = se; - break; - } - } - - // if none of them was master, throw an exception - if(serviceEndpoint == null) { - throw new InternalServerErrorException( - "Too many CKAN configuration on IS and no one with MASTER property"); - } - - } else { - serviceEndpoint = serviceEndpoints.get(0); - } - - Iterator accessPointIterator = serviceEndpoint.profile().accessPoints().iterator(); - while(accessPointIterator.hasNext()) { - AccessPoint accessPoint = accessPointIterator.next(); - - // add this host - ckanURL = accessPoint.address(); - - // retrieve sys admin token - sysAdminToken = accessPoint.propertyMap().get(API_KEY_PROPERTY).value(); - sysAdminToken = StringEncrypter.getEncrypter().decrypt(sysAdminToken); - - // retrieve option to check if the social post has to be made - socialPostEnabled = true; // default is true - if(accessPoint.propertyMap().containsKey(SOCIAL_POST)) { - if(accessPoint.propertyMap().get(SOCIAL_POST).value().trim().equalsIgnoreCase("false")) { - socialPostEnabled = false; - } - } - - // retrieve option for user alert - notificationToUsersEnabled = false; - if(accessPoint.propertyMap().containsKey(ALERT_USERS_ON_POST_CREATION)) { - if(accessPoint.propertyMap().get(ALERT_USERS_ON_POST_CREATION).value().trim() - .equalsIgnoreCase("true")) { - notificationToUsersEnabled = true; - } - } - - // retrieve URL_RESOLVER - if(accessPoint.propertyMap().containsKey(URL_RESOLVER)) { - uriResolverURL = accessPoint.propertyMap().get(URL_RESOLVER).value(); - } - - - moderationEnabled = false; - if(accessPoint.propertyMap().containsKey(MODERATION_ENABLED_KEY)) { - if(accessPoint.propertyMap().get(MODERATION_ENABLED_KEY).value().trim() - .equalsIgnoreCase("true")) { - moderationEnabled = true; - } - } - - } - - } catch(WebApplicationException e) { - throw e; - } catch(Exception e) { - throw new InternalServerErrorException("Error while getting configuration on IS", e); - } - - } - - public static final String GENERIC_RESOURCE_SECONDARY_TYPE_FOR_ORGANIZATIONS = "ApplicationProfile"; - public static final String GENERIC_RESOURCE_NAME_FOR_ORGANIZATIONS = "Supported CKAN Organizations"; - public static final String GENERIC_RESOURCE_CKAN_ORGANIZATIONS = "CKANOrganizations"; - - protected Set getSupportedOrganizationsFromIS() { - Set supportedOrganizations = new HashSet<>(); - - SimpleQuery query = ICFactory.queryFor(GenericResource.class); - query.addCondition(String.format("$resource/Profile/SecondaryType/text() eq '%s'", - GENERIC_RESOURCE_SECONDARY_TYPE_FOR_ORGANIZATIONS)); - query.addCondition( - String.format("$resource/Profile/Name/text() eq '%s'", GENERIC_RESOURCE_NAME_FOR_ORGANIZATIONS)); - - DiscoveryClient client = ICFactory.clientFor(GenericResource.class); - List resources = client.submit(query); - - if(resources == null || resources.size() == 0) { - logger.info( - "{} with SecondaryType {} and Name %s not found. Item will be only be created in {} CKAN organization", - GenericResource.class.getSimpleName(), GENERIC_RESOURCE_SECONDARY_TYPE_FOR_ORGANIZATIONS, - GENERIC_RESOURCE_NAME_FOR_ORGANIZATIONS, currentOrganizationName); - supportedOrganizations.add(currentOrganizationName); - } else { - try { - GenericResource genericResource = resources.get(0); - String body = genericResource.profile().body().getTextContent(); - ObjectMapper objectMapper = new ObjectMapper(); - JsonNode jsonNode = objectMapper.readTree(body); - ArrayNode array = (ArrayNode) jsonNode.get(GENERIC_RESOURCE_CKAN_ORGANIZATIONS); - for(int i = 0; i < array.size(); i++) { - String organization = array.get(i).asText(); - supportedOrganizations.add(organization); - } - }catch (Exception e) { - supportedOrganizations.clear(); - supportedOrganizations.add(currentOrganizationName); - } - } - - logger.debug("Supported CKAN Organization for current Context ({}) are {}", currentContext, - supportedOrganizations); - - return supportedOrganizations; - } - - - public String getUriResolverURL() throws Exception { - return uriResolverURL; - } - - public String getCKANURL() { - return ckanURL; - } - - public boolean isSocialPostEnabled() throws Exception { - return socialPostEnabled; - } - - public boolean isNotificationToUsersEnabled() throws Exception { - return notificationToUsersEnabled; - } - - public boolean isModerationEnabled() { - return moderationEnabled; - } - - public String getSysAdminToken() throws Exception { - return sysAdminToken; - } - - - public String getCurrentContext() { - return currentContext; - } - - - public ScopeBean getCurrentScopeBean() { - return currentScopeBean; - } - - - public String getCurrentOrganizationName() { - return currentOrganizationName; - } - - - public Set getSupportedOrganizations() { - return supportedOrganizations; - } - - - public void setModerationEnabled(boolean moderationEnabled) { - this.moderationEnabled = moderationEnabled; - } - -} diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java index 266a985..d455001 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java @@ -22,9 +22,9 @@ import org.apache.http.MethodNotSupportedException; import org.gcube.com.fasterxml.jackson.databind.JsonNode; import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode; import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode; -import org.gcube.common.scope.impl.ScopeBean; import org.gcube.common.scope.impl.ScopeBean.Type; import org.gcube.gcat.api.GCatConstants; +import org.gcube.gcat.api.configuration.CatalogueConfiguration; import org.gcube.gcat.api.moderation.CMItemStatus; import org.gcube.gcat.api.moderation.CMItemVisibility; import org.gcube.gcat.api.moderation.Moderated; @@ -120,8 +120,7 @@ public class CKANPackage extends CKAN implements Moderated { protected final CKANUser ckanUser; - protected final CKANInstance ckanInstance; - protected final Set supportedOrganizations; + protected final CatalogueConfiguration configuration; protected ModerationThread moderationThread; @@ -139,28 +138,19 @@ public class CKANPackage extends CKAN implements Moderated { ckanUser = CKANUserCache.getCurrrentCKANUser(); - ckanInstance = CKANInstance.getInstance(); - supportedOrganizations = ckanInstance.getSupportedOrganizations(); + configuration = CatalogueConfigurationFactory.getInstance(); - for(String supportedOrganization : supportedOrganizations) { + for(String supportedOrganization : configuration.getSupportedOrganizations()) { ckanUser.addUserToOrganization(supportedOrganization); } } - /* - * Return the CKAN organization name using the current context name - */ - public static String getOrganizationName(ScopeBean scopeBean) { - String contextName = scopeBean.name(); - return contextName.toLowerCase().replace(" ", "_"); - } - protected CKANOrganization checkGotOrganization(String gotOrganization) throws ForbiddenException { - if(!supportedOrganizations.contains(gotOrganization)) { + if(!configuration.getSupportedOrganizations().contains(gotOrganization)) { String error = String.format( "IS Configuration does not allow to publish in %s organizations. Allowed organization are: %s", - gotOrganization, supportedOrganizations); + gotOrganization, configuration.getSupportedOrganizations()); throw new ForbiddenException(error); } @@ -180,7 +170,7 @@ public class CKANPackage extends CKAN implements Moderated { if(ckanOrganization == null) { // owner organization must be specified if the token belongs to a VRE - String organizationFromContext = ckanInstance.getCurrentOrganizationName(); + String organizationFromContext = configuration.getOrganization(); ckanOrganization = checkGotOrganization(organizationFromContext); objectNode.put(OWNER_ORG_KEY, organizationFromContext); } @@ -545,9 +535,9 @@ public class CKANPackage extends CKAN implements Moderated { protected String getFilterForOrganizations() { StringWriter stringWriter = new StringWriter(); int i=1; - for(String organizationName : supportedOrganizations) { + for(String organizationName : configuration.getSupportedOrganizations()) { stringWriter.append(String.format(GCatConstants.ORGANIZATION_FILTER_TEMPLATE, organizationName)); - if(i!=supportedOrganizations.size()) { + if(i!=configuration.getSupportedOrganizations().size()) { // Please note that an item can only belong to a single organization. // Hence the query must put supported organizations in OR. stringWriter.append(" OR "); @@ -573,9 +563,9 @@ public class CKANPackage extends CKAN implements Moderated { String filter = getFilterForOrganizations(); q = String.format("%s AND %s", q, filter); }else { - organizations.removeAll(this.supportedOrganizations); + organizations.removeAll(configuration.getSupportedOrganizations()); if(organizations.size()>0) { - String error = String.format("It is not possible to query the following organizations %s. Supported organization in this context are %s", organizations.toString(), supportedOrganizations.toString()); + String error = String.format("It is not possible to query the following organizations %s. Supported organization in this context are %s", organizations.toString(), configuration.getSupportedOrganizations().toString()); throw new ForbiddenException(error); } } @@ -773,7 +763,7 @@ public class CKANPackage extends CKAN implements Moderated { } String catalogueItemURL = ""; - if(ckanInstance.getCurrentScopeBean().is(Type.VRE)) { + if(configuration.getScopeBean().is(Type.VRE)) { catalogueItemURL = addItemURLViaResolver(jsonNode); } @@ -786,7 +776,7 @@ public class CKANPackage extends CKAN implements Moderated { postItemCreated(); if(!isModerationEnabled()) { - if(ckanInstance.getCurrentScopeBean().is(Type.VRE)) { + if(configuration.getScopeBean().is(Type.VRE)) { // Actions performed after a package has been correctly created on ckan. String title = result.get(TITLE_KEY).asText(); sendSocialPost(title, catalogueItemURL); @@ -1043,7 +1033,7 @@ public class CKANPackage extends CKAN implements Moderated { } protected boolean isModerationEnabled() { - boolean moderationEnabled = ckanInstance.isModerationEnabled(); + boolean moderationEnabled = configuration.isModerationEnabled(); if(moderationEnabled && moderationThread==null) { moderationThread = ModerationThread.getDefaultInstance(); moderationThread.setCKANUser(ckanUser); @@ -1347,7 +1337,7 @@ public class CKANPackage extends CKAN implements Moderated { moderationThread.setItemCoordinates(itemID, name); moderationThread.postItemApproved(moderatorMessage); - if(ckanInstance.getCurrentScopeBean().is(Type.VRE)) { + if(configuration.getScopeBean().is(Type.VRE)) { // Actions performed after a package has been correctly created on ckan. String title = result.get(TITLE_KEY).asText(); String catalogueItemURL = getExtraField(result, EXTRAS_ITEM_URL_KEY).asText(); diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackageTrash.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackageTrash.java index 244f7ca..431eb91 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackageTrash.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackageTrash.java @@ -23,6 +23,7 @@ import org.gcube.common.encryption.encrypter.StringEncrypter; import org.gcube.common.resources.gcore.ServiceEndpoint; import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; import org.gcube.common.resources.gcore.ServiceEndpoint.Property; +import org.gcube.gcat.api.configuration.CatalogueConfiguration; import org.gcube.gcat.api.roles.Role; import org.gcube.resources.discovery.client.api.DiscoveryClient; import org.gcube.resources.discovery.client.queries.api.SimpleQuery; @@ -61,7 +62,7 @@ public class CKANPackageTrash { protected ObjectMapper mapper; protected final CKANUser ckanUser; - protected final CKANInstance ckanInstance; + protected final CatalogueConfiguration configuration; protected final Set supportedOrganizations; protected boolean ownOnly; @@ -74,9 +75,9 @@ public class CKANPackageTrash { mapper = new ObjectMapper(); ckanUser = CKANUserCache.getCurrrentCKANUser(); - ckanInstance = CKANInstance.getInstance(); + configuration = CatalogueConfigurationFactory.getInstance(); - supportedOrganizations = ckanInstance.getSupportedOrganizations(); + supportedOrganizations = configuration.getSupportedOrganizations(); for(String supportedOrganization : supportedOrganizations) { ckanUser.addUserToOrganization(supportedOrganization); } diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANUtility.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANUtility.java index 5602bcd..815aac6 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANUtility.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANUtility.java @@ -9,7 +9,7 @@ public class CKANUtility { public static String getSysAdminAPI() { try { - return CKANInstance.getInstance().getSysAdminToken(); + return CatalogueConfigurationFactory.getInstance().getSysAdminToken(); } catch(Exception e) { throw new InternalServerErrorException(e); } diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CatalogueConfigurationFactory.java b/src/main/java/org/gcube/gcat/persistence/ckan/CatalogueConfigurationFactory.java new file mode 100644 index 0000000..e4d1c2e --- /dev/null +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CatalogueConfigurationFactory.java @@ -0,0 +1,60 @@ +package org.gcube.gcat.persistence.ckan; + +import java.util.HashMap; +import java.util.Map; + +import org.gcube.common.authorization.utils.manager.SecretManager; +import org.gcube.gcat.api.configuration.CatalogueConfiguration; +import org.gcube.gcat.configuration.GCoreISConfigurationProxy; + +/** + * @author Luca Frosini (ISTI - CNR) + */ +public class CatalogueConfigurationFactory { + + private static final Map catalogueConfigurations; + + static { + catalogueConfigurations = new HashMap<>(); + } + + protected static CatalogueConfiguration load(String context) { + GCoreISConfigurationProxy gCoreISConfigurationProxy = new GCoreISConfigurationProxy(context); + return gCoreISConfigurationProxy.getCatalogueConfiguration(); + } + + public synchronized static CatalogueConfiguration getInstance() { + String context = SecretManager.instance.get().getContext(); + CatalogueConfiguration catalogueConfiguration = catalogueConfigurations.get(context); + if(catalogueConfiguration == null) { + catalogueConfiguration = load(context); + catalogueConfigurations.put(context, catalogueConfiguration); + } + return catalogueConfiguration; + } + + public synchronized static void renew() { + String context = SecretManager.instance.get().getContext(); + catalogueConfigurations.remove(context); + CatalogueConfiguration catalogueConfiguration = load(context); + catalogueConfigurations.put(context, catalogueConfiguration); + } + + public synchronized static void purge() { + // Remove the resource from IS + String context = SecretManager.instance.get().getContext(); + catalogueConfigurations.remove(context); + GCoreISConfigurationProxy gCoreISConfigurationProxy = new GCoreISConfigurationProxy(context); + gCoreISConfigurationProxy.delete(); + } + + public synchronized static CatalogueConfiguration createOrUpdate(CatalogueConfiguration catalogueConfiguration) { + String context = SecretManager.instance.get().getContext(); + catalogueConfigurations.remove(context); + GCoreISConfigurationProxy gCoreISConfigurationProxy = new GCoreISConfigurationProxy(context, catalogueConfiguration); + catalogueConfiguration = gCoreISConfigurationProxy.createOrUpdate(); + catalogueConfigurations.put(context, catalogueConfiguration); + return catalogueConfiguration; + } + +} diff --git a/src/main/java/org/gcube/gcat/rest/Configuration.java b/src/main/java/org/gcube/gcat/rest/Configuration.java new file mode 100644 index 0000000..8a753c3 --- /dev/null +++ b/src/main/java/org/gcube/gcat/rest/Configuration.java @@ -0,0 +1,268 @@ +package org.gcube.gcat.rest; + +import java.util.Iterator; + +import javax.ws.rs.BadRequestException; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; +import javax.xml.ws.WebServiceException; + +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; +import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode; +import org.gcube.common.authorization.utils.manager.SecretManager; +import org.gcube.gcat.ResourceInitializer; +import org.gcube.gcat.annotation.PATCH; +import org.gcube.gcat.annotation.PURGE; +import org.gcube.gcat.api.configuration.CatalogueConfiguration; +import org.gcube.gcat.persistence.ckan.CatalogueConfigurationFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Luca Frosini (ISTI - CNR) + */ +@Path(Configuration.CONFIGURATION) +public class Configuration extends BaseREST implements org.gcube.gcat.api.interfaces.Configuration { + + private static Logger logger = LoggerFactory.getLogger(Configuration.class); + + protected String checkContext(String context) throws WebServiceException { + if(context==null || context.compareTo("")==0) { + throw new BadRequestException("Please provide a valid context as path parameter"); + } + + String c = SecretManager.instance.get().getContext(); + if(context.compareTo(Configuration.CURRENT_CONTEXT_PATH_PARAMETER)==0) { + return c; + } + + if(context.compareTo(c)!=0) { + throw new BadRequestException("Context provided as path parameter (i.e. " + context + ") does not match with token request context (i.e. " + c + ")"); + } + + return c; + } + + protected String checkContext(String context, CatalogueConfiguration catalogueConfiguration) { + String c = checkContext(context); + if(c.compareTo(catalogueConfiguration.getContext())!=0) { + throw new BadRequestException("Context provided in the configuration (i.e. " + catalogueConfiguration.getContext() + ") does not match with token request context (i.e. " + c + ")"); + } + return c; + } + + private String createOrUpdate(ObjectMapper mapper, CatalogueConfiguration catalogueConfiguration) throws WebServiceException { + try { + CatalogueConfiguration gotCatalogueConfiguration = CatalogueConfigurationFactory.createOrUpdate(catalogueConfiguration); + String configuration = mapper.writeValueAsString(gotCatalogueConfiguration); + logger.debug("The new configuration in context {} is {}", catalogueConfiguration.getContext(), configuration); + return configuration; + }catch (WebServiceException e) { + throw e; + }catch (Exception e) { + throw new InternalServerErrorException(e); + } + } + + + @PUT + @Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) + @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) + public String createOrUpdate(String context, String json) throws WebServiceException { + try { + ObjectMapper mapper = new ObjectMapper(); + CatalogueConfiguration catalogueConfiguration = mapper.readValue(json, CatalogueConfiguration.class); + checkContext(context, catalogueConfiguration); + return createOrUpdate(mapper, catalogueConfiguration); + }catch (WebServiceException e) { + throw e; + }catch (Exception e) { + throw new InternalServerErrorException(e); + } + } + + + @POST + @Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) + @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) + @Override + public Response create(String json) throws WebServiceException { + try { + ObjectMapper mapper = new ObjectMapper(); + CatalogueConfiguration catalogueConfiguration = mapper.readValue(json, CatalogueConfiguration.class); + checkContext(CURRENT_CONTEXT_PATH_PARAMETER, catalogueConfiguration); + String ret = createOrUpdate(mapper, catalogueConfiguration); + ResponseBuilder responseBuilder = Response.status(Status.CREATED); + if(ret!=null) { + responseBuilder.entity(ret).type(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8); + } + return responseBuilder.build(); + }catch (WebServiceException e) { + throw e; + }catch (Exception e) { + throw new InternalServerErrorException(e); + } + } + + @GET + @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) + public String read(String context) throws WebServiceException { + try { + checkContext(context); + return read(); + }catch (WebServiceException e) { + throw e; + }catch (Exception e) { + throw new InternalServerErrorException(e); + } + } + + @Override + public String read() throws WebServiceException { + try { + CatalogueConfiguration catalogueConfiguration = CatalogueConfigurationFactory.getInstance(); + ObjectMapper mapper = new ObjectMapper(); + String configuration = mapper.writeValueAsString(catalogueConfiguration); + logger.debug("Configuration in context {} is {}", catalogueConfiguration.getContext(), configuration); + return configuration; + }catch (WebServiceException e) { + throw e; + }catch (Exception e) { + throw new InternalServerErrorException(e); + } + } + + @Override + public String update(String json) throws WebServiceException { + try { + ObjectMapper mapper = new ObjectMapper(); + CatalogueConfiguration catalogueConfiguration = mapper.readValue(json, CatalogueConfiguration.class); + checkContext(CURRENT_CONTEXT_PATH_PARAMETER); + catalogueConfiguration = CatalogueConfigurationFactory.createOrUpdate(catalogueConfiguration); + String configuration = mapper.writeValueAsString(catalogueConfiguration); + logger.debug("Configuration in context {} has been updated to {}", catalogueConfiguration.getContext(), configuration); + return configuration; + }catch (WebServiceException e) { + throw e; + }catch (Exception e) { + throw new InternalServerErrorException(e); + } + } + + @PATCH + @Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) + @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) + public String patch(String context, String json) throws WebServiceException { + try { + checkContext(context); + return patch(json); + }catch (WebServiceException e) { + throw e; + }catch (Exception e) { + throw new InternalServerErrorException(e); + } + } + + @Override + public String patch(String json) throws WebServiceException { + try { + CatalogueConfiguration catalogueConfiguration = CatalogueConfigurationFactory.getInstance(); + ObjectMapper mapper = new ObjectMapper(); + ObjectNode node = (ObjectNode) mapper.readTree(json); + + if(node.has(CatalogueConfiguration.CONTEXT_KEY)) { + String context = node.get(CatalogueConfiguration.CONTEXT_KEY).asText(); + String c = SecretManager.instance.get().getContext(); + if(c.compareTo(context)!=0) { + throw new BadRequestException("Context provided in the configuration (i.e. " + catalogueConfiguration.getContext() + ") does not match with token request context (i.e. " + c + ")"); + } + node.remove(CURRENT_CONTEXT_PATH_PARAMETER); + } + + ObjectNode configuration = mapper.valueToTree(catalogueConfiguration); + + Iterator fieldNames = node.fieldNames(); + while(fieldNames.hasNext()) { + String fieldName = fieldNames.next(); + configuration.set(fieldName, node.get(fieldName)); + } + + CatalogueConfiguration newCatalogueConfiguration = mapper.treeToValue(configuration, CatalogueConfiguration.class); + + newCatalogueConfiguration = CatalogueConfigurationFactory.createOrUpdate(newCatalogueConfiguration); + + catalogueConfiguration = CatalogueConfigurationFactory.createOrUpdate(catalogueConfiguration); + String ret = mapper.writeValueAsString(catalogueConfiguration); + logger.debug("Configuration in context {} has been patched to {}", catalogueConfiguration.getContext(), ret); + return ret; + }catch (WebServiceException e) { + throw e; + }catch (Exception e) { + throw new InternalServerErrorException(e); + } + } + + @DELETE + public Response delete(String context, Boolean purge) throws WebServiceException { + try { + checkContext(context); + if(purge) { + return purge(); + }else { + return delete(); + } + }catch (WebServiceException e) { + throw e; + }catch (Exception e) { + throw new InternalServerErrorException(e); + } + } + + // Remove the configuration from cache and force reload + @Override + public Response delete() throws WebServiceException { + try { + CatalogueConfigurationFactory.renew(); + return Response.status(Status.NO_CONTENT).build(); + }catch (WebServiceException e) { + throw e; + }catch (Exception e) { + throw new InternalServerErrorException(e); + } + } + + @PURGE + public Response purge(String context) throws WebServiceException { + try { + checkContext(context); + return purge(); + }catch (WebServiceException e) { + throw e; + }catch (Exception e) { + throw new InternalServerErrorException(e); + } + } + + // Remove the configuration from cache and from IS + @Override + public Response purge() throws WebServiceException { + try { + CatalogueConfigurationFactory.purge(); + return Response.status(Status.NO_CONTENT).build(); + }catch (WebServiceException e) { + throw e; + }catch (Exception e) { + throw new InternalServerErrorException(e); + } + } + +} diff --git a/src/main/java/org/gcube/gcat/social/SocialPost.java b/src/main/java/org/gcube/gcat/social/SocialPost.java index 6ca514d..48895e8 100644 --- a/src/main/java/org/gcube/gcat/social/SocialPost.java +++ b/src/main/java/org/gcube/gcat/social/SocialPost.java @@ -15,7 +15,8 @@ import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode; import org.gcube.common.authorization.utils.manager.SecretManager; import org.gcube.common.authorization.utils.socialservice.SocialService; import org.gcube.common.gxhttp.request.GXHTTPStringRequest; -import org.gcube.gcat.persistence.ckan.CKANInstance; +import org.gcube.gcat.persistence.ckan.CatalogueConfigurationFactory; +import org.gcube.gcat.api.configuration.CatalogueConfiguration; import org.gcube.gcat.persistence.ckan.CKANUserCache; import org.gcube.gcat.utils.Constants; import org.gcube.gcat.utils.HTTPUtility; @@ -117,7 +118,7 @@ public class SocialPost extends Thread { try { - CKANInstance instance = CKANInstance.getInstance(); + CatalogueConfiguration instance = CatalogueConfigurationFactory.getInstance(); if(!instance.isSocialPostEnabled()) { logger.info("Social Post are disabled in the context {}", SecretManager.instance.get().getContext()); diff --git a/src/test/java/org/gcube/gcat/configuration/GCoreISConfigurationProxyTest.java b/src/test/java/org/gcube/gcat/configuration/GCoreISConfigurationProxyTest.java new file mode 100644 index 0000000..b6a9ea4 --- /dev/null +++ b/src/test/java/org/gcube/gcat/configuration/GCoreISConfigurationProxyTest.java @@ -0,0 +1,102 @@ +package org.gcube.gcat.configuration; + +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; +import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode; +import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode; +import org.gcube.common.authorization.utils.manager.SecretManager; +import org.gcube.common.resources.gcore.GenericResource; +import org.gcube.common.resources.gcore.Resources; +import org.gcube.common.scope.impl.ScopeBean; +import org.gcube.gcat.ContextTest; +import org.gcube.gcat.api.configuration.CatalogueConfiguration; +import org.gcube.informationsystem.publisher.RegistryPublisher; +import org.gcube.informationsystem.publisher.RegistryPublisherFactory; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GCoreISConfigurationProxyTest extends ContextTest { + + private static final Logger logger = LoggerFactory.getLogger(GCoreISConfigurationProxyTest.class); + + @Test + public void testGetSupportedOrganizationsFromIS() throws Exception { + ContextTest.setContextByName("/gcube/devNext/NextNext"); + String context = SecretManager.instance.get().getContext(); + GCoreISConfigurationProxy gCoreISConfigurationProxy = new GCoreISConfigurationProxy(context); + Set organizations = gCoreISConfigurationProxy.getSupportedOrganizationsFromIS(); + Assert.assertTrue(organizations.size()>0); + } + + protected GenericResource instantiateGenericResource(String secondaryType, String name, String xml) throws Exception { + GenericResource genericResource = new GenericResource(); + org.gcube.common.resources.gcore.GenericResource.Profile profile = genericResource.newProfile(); + profile.type(secondaryType); + profile.name(name); + profile.description("This resource is read by gCat and define the list of CKAN organizations where a client is allowed to publish for the current context"); + profile.newBody(xml); + StringWriter stringWriter = new StringWriter(); + Resources.marshal(genericResource, stringWriter); + logger.debug("The generated {} is\n{}", GenericResource.class.getSimpleName(), stringWriter.toString()); + return genericResource; + } + + protected void createGenericResource(String xml) throws Exception { + GenericResource genericResource = instantiateGenericResource( + GCoreISConfigurationProxy.GENERIC_RESOURCE_SECONDARY_TYPE_FOR_ORGANIZATIONS, + GCoreISConfigurationProxy.GENERIC_RESOURCE_NAME_FOR_ORGANIZATIONS, xml); + RegistryPublisher registryPublisher = RegistryPublisherFactory.create(); + genericResource = registryPublisher.create(genericResource); + StringWriter stringWriter = new StringWriter(); + Resources.marshal(genericResource, stringWriter); + logger.trace("The {} with ID {} has been created \n{}", GenericResource.class.getSimpleName(), + genericResource.id(), stringWriter.toString()); + } + + protected String createGRBody(List organizations) throws Exception { + if(organizations==null || organizations.size()<1) { + throw new Exception("Unable to create the body for the generic resource with empty organization list"); + } + ObjectMapper objectMapper = new ObjectMapper(); + ObjectNode objectNode = objectMapper.createObjectNode(); + ArrayNode arrayNode = objectNode.putArray(GCoreISConfigurationProxy.GENERIC_RESOURCE_CKAN_ORGANIZATIONS); + for(String organizationName : organizations) { + arrayNode.add(organizationName); + } + return objectMapper.writeValueAsString(objectNode); + } + + protected void createGenericResourceForSupportedOrganizations(List organizations) throws Exception { + String json = createGRBody(organizations); + createGenericResource(json); + } + + // @Test + public void createGenericResourceForSupportedOrganizationsByName() throws Exception { + List organizations = new ArrayList<>(); + organizations.add("nextnext"); + organizations.add("devvre"); + createGenericResourceForSupportedOrganizations(organizations); + } + + // @Test + public void createGenericResourceForSupportedOrganizationsByScopeBean() throws Exception { + ContextTest.setContextByName("/gcube/devNext/NextNext"); + + List scopeBeans = new ArrayList<>(); + scopeBeans.add(new ScopeBean("/gcube/devNext/NextNext")); + scopeBeans.add(new ScopeBean("/gcube/devsec/devVRE")); + List organizations = new ArrayList<>(); + for(ScopeBean scopeBean : scopeBeans) { + organizations.add(CatalogueConfiguration.getOrganizationName(scopeBean)); + } + createGenericResourceForSupportedOrganizations(organizations); + } + +} diff --git a/src/test/java/org/gcube/gcat/persistence/ckan/CKANInstanceTest.java b/src/test/java/org/gcube/gcat/persistence/ckan/CKANInstanceTest.java new file mode 100644 index 0000000..2ddf555 --- /dev/null +++ b/src/test/java/org/gcube/gcat/persistence/ckan/CKANInstanceTest.java @@ -0,0 +1,21 @@ +package org.gcube.gcat.persistence.ckan; + +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; +import org.gcube.gcat.ContextTest; +import org.gcube.gcat.api.configuration.CatalogueConfiguration; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CKANInstanceTest extends ContextTest { + + private static Logger logger = LoggerFactory.getLogger(CKANInstanceTest.class); + + @Test + public void testSerialization() throws Exception { + CatalogueConfiguration configuration = CatalogueConfigurationFactory.getInstance(); + ObjectMapper mapper = new ObjectMapper(); + logger.debug("Configuration is {}", mapper.writeValueAsString(configuration)); + } + +} diff --git a/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java b/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java index 12db4c5..0a11fd9 100644 --- a/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java +++ b/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java @@ -8,7 +8,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import javax.ws.rs.ForbiddenException; import javax.ws.rs.NotFoundException; @@ -22,18 +21,14 @@ import org.gcube.com.fasterxml.jackson.databind.JsonNode; import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode; import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode; -import org.gcube.common.authorization.client.exceptions.ObjectNotFound; import org.gcube.common.authorization.library.provider.UserInfo; import org.gcube.common.authorization.utils.manager.SecretManager; -import org.gcube.common.resources.gcore.GenericResource; -import org.gcube.common.resources.gcore.Resources; import org.gcube.common.scope.impl.ScopeBean; import org.gcube.gcat.ContextTest; import org.gcube.gcat.api.GCatConstants; +import org.gcube.gcat.api.configuration.CatalogueConfiguration; import org.gcube.gcat.api.moderation.CMItemStatus; import org.gcube.gcat.api.moderation.Moderated; -import org.gcube.informationsystem.publisher.RegistryPublisher; -import org.gcube.informationsystem.publisher.RegistryPublisherFactory; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -186,7 +181,7 @@ public class CKANPackageTest extends ContextTest { public void listWithParameters() throws Exception { String contextName = "/gcube/devNext/NextNext"; ScopeBean scopeBean = new ScopeBean(contextName); - String ckanOrganizationName = CKANPackage.getOrganizationName(scopeBean); + String ckanOrganizationName = CatalogueConfiguration.getOrganizationName(scopeBean); ContextTest.setContextByName(contextName); CKANPackage ckanPackage = new CKANPackage(); @@ -253,79 +248,6 @@ public class CKANPackageTest extends ContextTest { } - protected GenericResource instantiateGenericResource(String secondaryType, String name, String xml) throws Exception { - GenericResource genericResource = new GenericResource(); - org.gcube.common.resources.gcore.GenericResource.Profile profile = genericResource.newProfile(); - profile.type(secondaryType); - profile.name(name); - profile.description("This resource is read by gCat and define the list of CKAN organizations where a client is allowed to publish for the current context"); - profile.newBody(xml); - StringWriter stringWriter = new StringWriter(); - Resources.marshal(genericResource, stringWriter); - logger.debug("The generated {} is\n{}", GenericResource.class.getSimpleName(), stringWriter.toString()); - return genericResource; - } - - protected void createGenericResource(String xml) throws Exception { - GenericResource genericResource = instantiateGenericResource( - CKANInstance.GENERIC_RESOURCE_SECONDARY_TYPE_FOR_ORGANIZATIONS, - CKANInstance.GENERIC_RESOURCE_NAME_FOR_ORGANIZATIONS, xml); - RegistryPublisher registryPublisher = RegistryPublisherFactory.create(); - genericResource = registryPublisher.create(genericResource); - StringWriter stringWriter = new StringWriter(); - Resources.marshal(genericResource, stringWriter); - logger.trace("The {} with ID {} has been created \n{}", GenericResource.class.getSimpleName(), - genericResource.id(), stringWriter.toString()); - } - - protected String createGRBody(List organizations) throws Exception { - if(organizations==null || organizations.size()<1) { - throw new Exception("Unable to create the body for the generic resource with empty organization list"); - } - ObjectMapper objectMapper = new ObjectMapper(); - ObjectNode objectNode = objectMapper.createObjectNode(); - ArrayNode arrayNode = objectNode.putArray(CKANInstance.GENERIC_RESOURCE_CKAN_ORGANIZATIONS); - for(String organizationName : organizations) { - arrayNode.add(organizationName); - } - return objectMapper.writeValueAsString(objectNode); - } - - protected void createGenericResourceForSupportedOrganizations(List organizations) throws Exception { - String json = createGRBody(organizations); - createGenericResource(json); - } - - // @Test - public void createGenericResourceForSupportedOrganizationsByName() throws Exception { - List organizations = new ArrayList<>(); - organizations.add("nextnext"); - organizations.add("devvre"); - createGenericResourceForSupportedOrganizations(organizations); - } - - // @Test - public void createGenericResourceForSupportedOrganizationsByScopeBean() throws Exception { - ContextTest.setContextByName("/gcube/devNext/NextNext"); - - List scopeBeans = new ArrayList<>(); - scopeBeans.add(new ScopeBean("/gcube/devNext/NextNext")); - scopeBeans.add(new ScopeBean("/gcube/devsec/devVRE")); - List organizations = new ArrayList<>(); - for(ScopeBean scopeBean : scopeBeans) { - organizations.add(CKANPackage.getOrganizationName(scopeBean)); - } - createGenericResourceForSupportedOrganizations(organizations); - } - - @Test - public void testGetSupportedOrganizationsFromIS() throws ObjectNotFound, Exception { - ContextTest.setContextByName("/gcube/devNext/NextNext"); - CKANInstance ckanInstance = CKANInstance.getInstance(); - Set organizations = ckanInstance.getSupportedOrganizationsFromIS(); - Assert.assertTrue(organizations.size()>0); - } - @Test(expected=ForbiddenException.class) public void checkParameter() throws Exception { @@ -391,7 +313,7 @@ public class CKANPackageTest extends ContextTest { protected CKANPackage createPackage(ObjectMapper mapper, Boolean socialPost) throws Exception { String currentContext = SecretManager.instance.get().getContext(); ScopeBean scopeBean = new ScopeBean(currentContext); - String ckanOrganizationName = CKANPackage.getOrganizationName(scopeBean); + String organization = CatalogueConfiguration.getOrganizationName(scopeBean); ObjectNode itemObjectNode = mapper.createObjectNode(); itemObjectNode.put(CKAN.NAME_KEY, ITEM_NAME_VALUE); @@ -400,7 +322,7 @@ public class CKANPackageTest extends ContextTest { itemObjectNode.put(PRIVATE_KEY, false); itemObjectNode.put(NOTES_KEY, "A research of Luca Frosini"); itemObjectNode.put(URL_KEY, "https://www.d4science.org"); - itemObjectNode.put(CKANPackage.OWNER_ORG_KEY, ckanOrganizationName); + itemObjectNode.put(CKANPackage.OWNER_ORG_KEY, organization); ArrayNode tagArrayNode = itemObjectNode.putArray(CKANPackage.TAGS_KEY); ObjectNode tagNode = mapper.createObjectNode();