diff --git a/distro/changelog.xml b/distro/changelog.xml index 05edf43..47ecc7d 100644 --- a/distro/changelog.xml +++ b/distro/changelog.xml @@ -1,4 +1,8 @@ + + Added delegate roles method + Minor fixes diff --git a/pom.xml b/pom.xml index 1492b7c..4fe6315 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.gcube.data-catalogue ckan-util-library - 2.3.2-SNAPSHOT + 2.4.0-SNAPSHOT jar CKan utility library diff --git a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/server/DataCatalogue.java b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/server/DataCatalogue.java index ddcf204..8c82e52 100644 --- a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/server/DataCatalogue.java +++ b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/server/DataCatalogue.java @@ -594,5 +594,12 @@ public interface DataCatalogue { * @return a boolean value */ boolean isNotificationToUsersEnabled(); - + + /** + * Check if the user identified by username has to be registered in other organizations with some role. + * @param username + * @param sourceOrganization + * @param currentRole + */ + void assignRolesOtherOrganization(String username, String sourceOrganization, RolesCkanGroupOrOrg currentRole); } diff --git a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/server/DataCatalogueImpl.java b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/server/DataCatalogueImpl.java index f480461..dfe4d5e 100644 --- a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/server/DataCatalogueImpl.java +++ b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/server/DataCatalogueImpl.java @@ -87,6 +87,7 @@ public class DataCatalogueImpl implements DataCatalogue{ private boolean MANAGE_PRODUCT_BUTTON; private boolean ALERT_USERS_ON_POST_CREATION; private String CONTEXT; + private Map extendRoleInOrganization; private final static String PATH_SET_PRIVATE_DATASET = "/api/3/action/bulk_update_private"; private final static String PATH_SET_PUBLIC_DATASET = "/api/3/action/bulk_update_public"; @@ -143,7 +144,9 @@ public class DataCatalogueImpl implements DataCatalogue{ // save the context CONTEXT = scope; - + + // extended roles + extendRoleInOrganization = runningInstance.getExtendRoleInOrganization(); } @Override @@ -2811,4 +2814,37 @@ public class DataCatalogueImpl implements DataCatalogue{ return ALERT_USERS_ON_POST_CREATION; } + @Override + public void assignRolesOtherOrganization(String username, + String sourceOrganization, RolesCkanGroupOrOrg currentRole) { + + checkNotNull(username); + checkNotNull(sourceOrganization); + checkNotNull(currentRole); + + Iterator> iterator = extendRoleInOrganization.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = (Map.Entry) iterator + .next(); + + String sourceOrg = entry.getKey().split(DataCatalogueRunningCluster.ROLE_ORGANIZATION_SEPARATOR)[0]; + String role = entry.getKey().split(DataCatalogueRunningCluster.ROLE_ORGANIZATION_SEPARATOR)[1]; + String destOrg = entry.getValue(); + + if(sourceOrg.equals(sourceOrganization)){ + + RolesCkanGroupOrOrg ckanRole; + if(role.equals(DataCatalogueRunningCluster.CKAN_GENERIC_ROLE)) + ckanRole = currentRole; + else + ckanRole = RolesCkanGroupOrOrg.convertFromCapacity(role); + + logger.info("Checking for extra role: role is " + ckanRole + " and organization is " + destOrg); + checkRoleIntoOrganization(username, destOrg, ckanRole); + } + + } + + } + } \ No newline at end of file diff --git a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/server/DataCatalogueRunningCluster.java b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/server/DataCatalogueRunningCluster.java index 9a888c9..e9e87d2 100644 --- a/src/main/java/org/gcube/datacatalogue/ckanutillibrary/server/DataCatalogueRunningCluster.java +++ b/src/main/java/org/gcube/datacatalogue/ckanutillibrary/server/DataCatalogueRunningCluster.java @@ -4,13 +4,17 @@ import static org.gcube.resources.discovery.icclient.ICFactory.client; import static org.gcube.resources.discovery.icclient.ICFactory.clientFor; import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; +import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import org.gcube.common.encryption.StringEncrypter; import org.gcube.common.resources.gcore.ServiceEndpoint; @@ -28,8 +32,11 @@ import org.gcube.resources.discovery.client.queries.api.SimpleQuery; import org.gcube.resources.discovery.client.queries.impl.QueryBox; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; import org.w3c.dom.Node; +import org.w3c.dom.NodeList; import org.xml.sax.InputSource; +import org.xml.sax.SAXException; /** * Retrieve ckan running instance information in the infrastructure (for both its database and data catalogue url) @@ -60,6 +67,9 @@ public class DataCatalogueRunningCluster { // url of the http uri for this scope private final static String URL_RESOLVER = "URL_RESOLVER"; + // Other generic resource for delegating roles in groups to users + private final static String CATALOGUE_EXTENDING_ROLES = "CatalogueDelegateRoles"; + // retrieved data private List datacatalogueUrls = new ArrayList(); private List hostsDB = new ArrayList(); @@ -71,6 +81,11 @@ public class DataCatalogueRunningCluster { private boolean manageProductEnabled; private String urlResolver; private boolean alertUsers; + private Map extendRoleInOrganization; + + // generic role key + public static final String CKAN_GENERIC_ROLE = "*"; + public static final String ROLE_ORGANIZATION_SEPARATOR = "|"; // this token is needed in order to assign roles to user private String sysAdminToken; @@ -105,6 +120,10 @@ public class DataCatalogueRunningCluster { portletUrl = getPortletUrlFromInfrastrucure(); + // and parse the CatalogueDelegateRole resource, if any, in this context + extendRoleInOrganization = new HashMap(); + parseExtendingRoles(); + }catch(Exception e) { logger.warn("The following error occurred: " + e.toString()); throw e; @@ -113,6 +132,7 @@ public class DataCatalogueRunningCluster { } } + /** * Evaluate the right configuration about ckan * @param resources @@ -380,6 +400,63 @@ public class DataCatalogueRunningCluster { } + /** + * Parse the CatalogueDelegateRoles in this context + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + */ + private void parseExtendingRoles() throws ParserConfigurationException, SAXException, IOException { + + Query q = new QueryBox("for $profile in collection('/db/Profiles/GenericResource')//Resource " + + "where $profile/Profile/SecondaryType/string() eq 'ApplicationProfile' and $profile/Profile/Name/string() " + + " eq '" + CATALOGUE_EXTENDING_ROLES + "'" + + "return $profile"); + + DiscoveryClient client = client(); + List appProfile = client.submit(q); + + logger.debug("Resource for extending role has size " + appProfile.size()); + + if (appProfile == null || appProfile.size() == 0) + return; + else { + String profile = appProfile.get(0); + DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Node node = docBuilder.parse(new InputSource(new StringReader(profile))).getDocumentElement(); + XPathHelper helper = new XPathHelper(node); + + // fetch delegate elements + NodeList delegates = helper.evaluateForNodes("/Resource/Profile/Body/delegates/delegate"); + if (delegates != null && delegates.getLength() > 0) { + + for(int i = 0; i < delegates.getLength(); i++){ + + Node nodeI = delegates.item(i); + + if(nodeI.getNodeType() == Node.ELEMENT_NODE) { + + Element elem = (Element)nodeI; + String role = elem.getElementsByTagName("sourceRole").item(0).getTextContent(); + String destOrg = elem.getElementsByTagName("destOrganization").item(0).getTextContent(); + String sourceOrg = elem.getElementsByTagName("sourceOrganization").item(0).getTextContent(); + + if(destOrg == null || sourceOrg == null) + continue; + + extendRoleInOrganization.put(sourceOrg + ROLE_ORGANIZATION_SEPARATOR + role, destOrg); + + } + } + } + + } + + + logger.debug("Extended role map in this scope is " + extendRoleInOrganization); + + } + /** Retrieve the ckan portlet url * @return the portletUrl */ @@ -465,4 +542,13 @@ public class DataCatalogueRunningCluster { return alertUsers; } + + /** + * Get roles to extend + * @return Map + */ + public Map getExtendRoleInOrganization() { + return extendRoleInOrganization; + } + }