diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/security/SecurityContext.java b/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/security/SecurityContext.java index cd7ac38..7c83185 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/security/SecurityContext.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/security/SecurityContext.java @@ -26,6 +26,8 @@ import org.slf4j.LoggerFactory; import com.orientechnologies.orient.core.db.ODatabasePool; import com.orientechnologies.orient.core.db.ODatabaseSession; import com.orientechnologies.orient.core.db.document.ODatabaseDocument; +import com.orientechnologies.orient.core.db.record.OIdentifiable; +import com.orientechnologies.orient.core.db.record.ORecordLazySet; import com.orientechnologies.orient.core.metadata.security.ORestrictedOperation; import com.orientechnologies.orient.core.metadata.security.ORole; import com.orientechnologies.orient.core.metadata.security.OSecurity; @@ -253,7 +255,11 @@ public class SecurityContext { return context; } - public String getSecurityRoleOrUserName(PermissionMode permissionMode, SecurityType securityType, + public static String getRoleOrUserName(PermissionMode permissionMode, SecurityType securityType) { + return getRoleOrUserName(permissionMode, securityType, false); + } + + public static String getRoleOrUserName(PermissionMode permissionMode, SecurityType securityType, boolean hierarchic) { StringBuilder stringBuilder = new StringBuilder(); if(hierarchic) { @@ -261,6 +267,14 @@ public class SecurityContext { } stringBuilder.append(permissionMode); stringBuilder.append(securityType); + return stringBuilder.toString(); + } + + + public String getSecurityRoleOrUserName(PermissionMode permissionMode, SecurityType securityType, + boolean hierarchic) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(getRoleOrUserName(permissionMode, securityType, hierarchic)); stringBuilder.append("_"); stringBuilder.append(context.toString()); return stringBuilder.toString(); @@ -270,6 +284,27 @@ public class SecurityContext { return oDatabaseDocument.getMetadata().getSecurity(); } + public static Set getContexts(OElement element) { + Set contexts = new HashSet<>(); + ORecordLazySet oRecordLazySet = element.getProperty(OSecurity.ALLOW_ALL_FIELD); + for (OIdentifiable oIdentifiable : oRecordLazySet) { + ODocument oDocument = (ODocument) oIdentifiable; + String name = oDocument.getProperty("name"); + if (name.startsWith(getRoleOrUserName(PermissionMode.WRITER, SecurityType.ROLE)) + || name.startsWith(getRoleOrUserName(PermissionMode.READER, SecurityType.ROLE))) { + String[] list = name.split("_"); + if (list.length == 2) { + String contextUUID = list[1]; + if (!DatabaseEnvironment.RESERVED_CONTEX_UUID_STRING.contains(contextUUID)) { + contexts.add(contextUUID); + } + } + } + } + return contexts; + } + + public void addElement(OElement element) throws ResourceRegistryException { ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal(); ODatabaseDocument adminDatabaseDocument = getAdminDatabaseDocument(); diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/dbinitialization/DatabaseEnvironment.java b/src/main/java/org/gcube/informationsystem/resourceregistry/dbinitialization/DatabaseEnvironment.java index c5b5dfd..e31d571 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/dbinitialization/DatabaseEnvironment.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/dbinitialization/DatabaseEnvironment.java @@ -6,10 +6,12 @@ import java.net.URL; import java.security.Key; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.ServiceLoader; +import java.util.Set; import java.util.UUID; import org.gcube.common.encryption.SymmetricKey; @@ -128,6 +130,9 @@ public class DatabaseEnvironment { private static final String CONTEXT_SECURITY_CONTEXT; public static final UUID CONTEXT_SECURITY_CONTEXT_UUID; + public static final Set RESERVED_CONTEX_UUID_STRING; + public static final Set RESERVED_CONTEX_UUID; + protected static final String DB_KEY_FILENAME_VARNAME = "DB_KEY_FILENAME"; protected static final String DB_KEY_ALGORITHM_VARNAME = "DB_KEY_ALGORITHM"; @@ -188,16 +193,26 @@ public class DatabaseEnvironment { throw new RuntimeException("Unable to load properties", e); } + RESERVED_CONTEX_UUID_STRING = new HashSet<>(); + RESERVED_CONTEX_UUID = new HashSet<>(); + + ADMIN_SECURITY_CONTEXT = "00000000-0000-0000-0000-000000000000"; + RESERVED_CONTEX_UUID_STRING.add(ADMIN_SECURITY_CONTEXT); ADMIN_SECURITY_CONTEXT_UUID = UUID.fromString(ADMIN_SECURITY_CONTEXT); + RESERVED_CONTEX_UUID.add(ADMIN_SECURITY_CONTEXT_UUID); // Used to persist Schemas SCHEMA_SECURITY_CONTEXT = "eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee"; + RESERVED_CONTEX_UUID_STRING.add(SCHEMA_SECURITY_CONTEXT); SCHEMA_SECURITY_CONTEXT_UUID = UUID.fromString(SCHEMA_SECURITY_CONTEXT); + RESERVED_CONTEX_UUID.add(SCHEMA_SECURITY_CONTEXT_UUID); // Used to Persist Context and their relations CONTEXT_SECURITY_CONTEXT = "ffffffff-ffff-ffff-ffff-ffffffffffff"; + RESERVED_CONTEX_UUID_STRING.add(CONTEXT_SECURITY_CONTEXT); CONTEXT_SECURITY_CONTEXT_UUID = UUID.fromString(CONTEXT_SECURITY_CONTEXT); + RESERVED_CONTEX_UUID.add(CONTEXT_SECURITY_CONTEXT_UUID); try { boolean created = initGraphDB(); @@ -295,7 +310,7 @@ public class DatabaseEnvironment { KEY = initDbKey(properties); } - + protected static Key initDbKey(Properties properties) { try { logger.trace("Going to get properties required to load DB key"); diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/base/ElementManagement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/base/ElementManagement.java index bc39e34..4ad52e3 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/base/ElementManagement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/base/ElementManagement.java @@ -37,6 +37,7 @@ import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegis import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextException; import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaException; import org.gcube.informationsystem.resourceregistry.contexts.ContextUtility; +import org.gcube.informationsystem.resourceregistry.contexts.security.AdminSecurityContext; import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext; import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext.PermissionMode; import org.gcube.informationsystem.resourceregistry.dbinitialization.DatabaseEnvironment; @@ -760,6 +761,37 @@ public abstract class ElementManagement { } } + public String getContexts() throws NotFoundException, ContextException, ResourceRegistryException { + logger.debug("Going to get contexts for {} with UUID", elementType, uuid); + ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal(); + try { + AdminSecurityContext adminSecurityContext = ContextUtility.getAdminSecurityContext(); + oDatabaseDocument = adminSecurityContext.getDatabaseDocument(PermissionMode.READER); + + Set contexts = SecurityContext.getContexts(getElement()); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode arrayNode = objectMapper.createArrayNode(); + for(String contextUUID : contexts) { + arrayNode.add(contextUUID); + } + return objectMapper.writeValueAsString(arrayNode); + } catch(ResourceRegistryException e) { + logger.error("Unable to get contexts for {} with UUID {}", elementType, uuid, e); + throw e; + } catch(Exception e) { + logger.error("Unable to get contexts for {} with UUID {}", elementType, uuid, e); + throw new ContextException(e); + } finally { + if(oDatabaseDocument != null) { + oDatabaseDocument.close(); + } + + if(current!=null) { + current.activateOnCurrentThread(); + } + } + } + public static String getClassProperty(JsonNode jsonNode) { if(jsonNode.has(Element.CLASS_PROPERTY)) { return jsonNode.get(Element.CLASS_PROPERTY).asText(); diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/rest/SharingManagement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/rest/SharingManagement.java index affe7a3..c14c8d1 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/rest/SharingManagement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/rest/SharingManagement.java @@ -3,14 +3,17 @@ package org.gcube.informationsystem.resourceregistry.rest; import java.util.UUID; import javax.ws.rs.DELETE; +import javax.ws.rs.GET; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import org.gcube.common.authorization.library.provider.CalledMethodProvider; import org.gcube.informationsystem.context.reference.entities.Context; +import org.gcube.informationsystem.resourceregistry.ResourceInitializer; import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextNotFoundException; import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resource.ResourceNotFoundException; @@ -38,6 +41,38 @@ public class SharingManagement { } */ + /* + * GET /sharing/{TYPE_NAME}/{UUID}/contexts/ + * e.g GET /resource-registry/sharing/HostingNode/16032d09-3823-444e-a1ff-a67de4f350a8/contexts + * Where 16032d09-3823-444e-a1ff-a67de4f350a8 is the HostingNode UUID + * + * Return a list of UUID identifying the context the instance belongs to. + */ + @GET + @Path("{" + AccessPath.TYPE_PATH_PARAM + "}" + "/{" + AccessPath.UUID_PATH_PARAM + "}" + + SharingPath.CONTEXTS_PATH_PART ) + @Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) + public String listContexts(@PathParam(AccessPath.CONTEXT_UUID_PATH_PARAM) String contextId, + @PathParam(AccessPath.TYPE_PATH_PARAM) String type, @PathParam(AccessPath.UUID_PATH_PARAM) String instanceId) + throws ResourceNotFoundException, ContextNotFoundException, ResourceRegistryException { + + logger.info("Requested to add {} with UUID {} to {} with UUID {}", type, instanceId, Context.NAME, contextId); + // setRESTCalledMethod(HTTPMETHOD.PUT, type); + CalledMethodProvider.instance.set("listInstanceContexts"); + + @SuppressWarnings("rawtypes") + ElementManagement erManagement = ElementManagementUtility.getERManagement(type); + UUID uuid = null; + try { + uuid = UUID.fromString(instanceId); + } catch(Exception e) { + throw new ResourceRegistryException(e); + } + erManagement.setUUID(uuid); + return erManagement.getContexts(); + } + + /* * PUT /sharing/{TYPE_NAME}/{UUID}/contexts/{CONTEXT_UUID} * e.g PUT @@ -49,23 +84,23 @@ public class SharingManagement { @PUT @Path("{" + AccessPath.TYPE_PATH_PARAM + "}" + "/{" + AccessPath.UUID_PATH_PARAM + "}" + SharingPath.CONTEXTS_PATH_PART + "/{" + AccessPath.CONTEXT_UUID_PATH_PARAM + "}" ) - public boolean add(@PathParam(AccessPath.CONTEXT_UUID_PATH_PARAM) String contextId, - @PathParam(AccessPath.TYPE_PATH_PARAM) String type, @PathParam(AccessPath.UUID_PATH_PARAM) String id) + public boolean add(@PathParam(AccessPath.TYPE_PATH_PARAM) String type, @PathParam(AccessPath.UUID_PATH_PARAM) String instanceId, + @PathParam(AccessPath.CONTEXT_UUID_PATH_PARAM) String contextId) throws ResourceNotFoundException, ContextNotFoundException, ResourceRegistryException { - logger.info("Requested to add {} with UUID {} to {} with UUID {}", type, id, Context.NAME, contextId); + logger.info("Requested to add {} with UUID {} to {} with UUID {}", type, instanceId, Context.NAME, contextId); // setRESTCalledMethod(HTTPMETHOD.PUT, type); CalledMethodProvider.instance.set("addToContext"); @SuppressWarnings("rawtypes") - ElementManagement erManagement = ElementManagementUtility.getERManagement(type); + ElementManagement elementManagement = ElementManagementUtility.getERManagement(type); UUID uuid = null; try { - uuid = UUID.fromString(id); + uuid = UUID.fromString(instanceId); } catch(Exception e) { throw new ResourceRegistryException(e); } - erManagement.setUUID(uuid); + elementManagement.setUUID(uuid); UUID contextUUID = null; try { @@ -74,7 +109,7 @@ public class SharingManagement { throw new ResourceRegistryException(e); } - return erManagement.addToContext(contextUUID); + return elementManagement.addToContext(contextUUID); } /* @@ -88,24 +123,24 @@ public class SharingManagement { @DELETE @Path("{" + AccessPath.TYPE_PATH_PARAM + "}" + "/{" + AccessPath.UUID_PATH_PARAM + "}" + SharingPath.CONTEXTS_PATH_PART + "/{" + AccessPath.CONTEXT_UUID_PATH_PARAM + "}" ) - public Response remove(@PathParam(AccessPath.CONTEXT_UUID_PATH_PARAM) String contextId, - @PathParam(AccessPath.TYPE_PATH_PARAM) String type, @PathParam(AccessPath.UUID_PATH_PARAM) String id) + public Response remove(@PathParam(AccessPath.TYPE_PATH_PARAM) String type, @PathParam(AccessPath.UUID_PATH_PARAM) String instanceId, + @PathParam(AccessPath.CONTEXT_UUID_PATH_PARAM) String contextId) throws ResourceNotFoundException, ContextNotFoundException, ResourceRegistryException { - logger.info("Requested to remove {} with UUID {} to {} with UUID {}", type, id, Context.NAME, contextId); + logger.info("Requested to remove {} with UUID {} to {} with UUID {}", type, instanceId, Context.NAME, contextId); // setRESTCalledMethod(HTTPMETHOD.DELETE, type); CalledMethodProvider.instance.set("removeFromContext"); @SuppressWarnings("rawtypes") - ElementManagement erManagement = ElementManagementUtility.getERManagement(type); + ElementManagement elementManagement = ElementManagementUtility.getERManagement(type); UUID uuid = null; try { - uuid = UUID.fromString(id); + uuid = UUID.fromString(instanceId); } catch(Exception e) { throw new ResourceRegistryException(e); } - erManagement.setUUID(uuid); + elementManagement.setUUID(uuid); UUID contextUUID = null; try { @@ -114,7 +149,7 @@ public class SharingManagement { throw new ResourceRegistryException(e); } - erManagement.removeFromContext(contextUUID); + elementManagement.removeFromContext(contextUUID); return Response.status(Status.NO_CONTENT).build(); } diff --git a/src/test/java/org/gcube/informationsystem/resourceregistry/instances/multicontext/BasicTest.java b/src/test/java/org/gcube/informationsystem/resourceregistry/instances/multicontext/BasicTest.java index 4cc151b..5088a47 100644 --- a/src/test/java/org/gcube/informationsystem/resourceregistry/instances/multicontext/BasicTest.java +++ b/src/test/java/org/gcube/informationsystem/resourceregistry/instances/multicontext/BasicTest.java @@ -8,6 +8,7 @@ import java.net.URL; import java.util.Calendar; import java.util.UUID; +import org.gcube.common.authorization.client.exceptions.ObjectNotFound; import org.gcube.informationsystem.model.impl.properties.PropagationConstraintImpl; import org.gcube.informationsystem.model.reference.entities.Facet; import org.gcube.informationsystem.model.reference.properties.PropagationConstraint; @@ -22,6 +23,8 @@ import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resour import org.gcube.informationsystem.resourceregistry.api.exceptions.relation.RelationAvailableInAnotherContextException; import org.gcube.informationsystem.resourceregistry.contexts.ContextUtility; import org.gcube.informationsystem.resourceregistry.instances.SmartgearResourcesTest; +import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagement; +import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagementUtility; import org.gcube.informationsystem.resourceregistry.instances.model.entities.FacetManagement; import org.gcube.informationsystem.resourceregistry.instances.model.entities.ResourceManagement; import org.gcube.informationsystem.resourceregistry.instances.model.relations.IsRelatedToManagement; @@ -460,5 +463,25 @@ public class BasicTest extends ContextTest { boolean deleted = resourceManagement.delete(); Assert.assertTrue(deleted); } + + @Test + public void testGetInstanceContexts() throws ObjectNotFound, Exception { + + String type = "ContainerStateFacet"; + String instanceId = "9d22d8e2-56ad-4de4-99cd-3c68e282ba99"; + + @SuppressWarnings("rawtypes") + ElementManagement erManagement = ElementManagementUtility.getERManagement(type); + UUID uuid = null; + try { + uuid = UUID.fromString(instanceId); + } catch(Exception e) { + throw new ResourceRegistryException(e); + } + erManagement.setUUID(uuid); + String contexts = erManagement.getContexts(); + logger.debug("{}", contexts); + + } }