From f722c2b14851dcaca8c6c581435931a041c68704 Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Thu, 4 Feb 2021 14:05:52 +0100 Subject: [PATCH] Implementing add/remove to/from context no follow #20531 --- .../instances/base/ElementManagement.java | 140 ++++++++++++++---- .../base/ElementManagementUtility.java | 23 +++ .../model/entities/EntityManagement.java | 17 ++- .../resourceregistry/rest/SharingManager.java | 22 +-- 4 files changed, 152 insertions(+), 50 deletions(-) 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 3b8167a..b19baf3 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 @@ -36,13 +36,14 @@ import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundExcep import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextException; import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaException; +import org.gcube.informationsystem.resourceregistry.api.rest.SharingPath.SharingOperation; 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; import org.gcube.informationsystem.resourceregistry.instances.base.properties.PropertyElementManagement; -import org.gcube.informationsystem.resourceregistry.instances.model.OperationValidator; +import org.gcube.informationsystem.resourceregistry.instances.model.SharingOperationValidator; import org.gcube.informationsystem.resourceregistry.utils.HeaderOrient; import org.gcube.informationsystem.resourceregistry.utils.HeaderUtility; import org.gcube.informationsystem.resourceregistry.utils.Utility; @@ -771,13 +772,63 @@ public abstract class ElementManagement { } } - public Map addToContext(UUID contextUUID) + public static Map addToContextNoPropagationConstraint(Map expectedInstances, UUID contextUUID, boolean dryRun) throws NotFoundException, ContextException, ResourceRegistryException { - return addToContext(contextUUID, null); + Set instances = expectedInstances.keySet(); + staticLogger.info("Going to add {} to Context with UUID {} not following Propagation Constraints", instances, contextUUID); + ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal(); + ODatabaseDocument oDatabaseDocument = null; + try { + oDatabaseDocument = ContextUtility.getAdminSecurityContext().getDatabaseDocument(PermissionMode.WRITER); + oDatabaseDocument.begin(); + + SecurityContext targetSecurityContext = ContextUtility.getInstance().getSecurityContextByUUID(contextUUID); + + Map affectedInstances = new HashMap<>(); + + for(UUID uuid : expectedInstances.keySet()) { + String type = expectedInstances.get(uuid).get(Element.CLASS_PROPERTY).asText(); + ElementManagement elementManagement = ElementManagementUtility.getERManagement(oDatabaseDocument, type); + elementManagement.setUUID(uuid); + elementManagement.setHonourPropagationConstraintsInContextSharing(false); + elementManagement.setDryRunContextSharing(dryRun); + + affectedInstances.putAll(elementManagement.internalAddToContext(targetSecurityContext)); + } + + SharingOperationValidator operationValidator = new SharingOperationValidator(expectedInstances, SharingOperation.ADD); + + if(operationValidator.isValidOperation(affectedInstances)) { + oDatabaseDocument.commit(); + } + + staticLogger.info("{} successfully added to Context with UUID {} not following Propagation Constraints", instances, contextUUID); + + return affectedInstances; + } catch(ResourceRegistryException e) { + staticLogger.error("Unable to add {} to Context with UUID {} not following Propagation Constraints - Reason is {}", instances, contextUUID, e.getMessage()); + if(oDatabaseDocument != null) { + oDatabaseDocument.rollback(); + } + throw e; + } catch(Exception e) { + staticLogger.error("Unable to add {} to Context with UUID {} not following Propagation Constraints.", instances, contextUUID, e.getMessage()); + if(oDatabaseDocument != null) { + oDatabaseDocument.rollback(); + } + throw new ContextException(e); + } finally { + if(oDatabaseDocument != null) { + oDatabaseDocument.close(); + } + + if(current!=null) { + current.activateOnCurrentThread(); + } + } } - public Map addToContext(UUID contextUUID, OperationValidator operationValidator) - throws NotFoundException, ContextException, ResourceRegistryException { + public Map addToContext(UUID contextUUID) throws NotFoundException, ContextException, ResourceRegistryException { logger.info("Going to add {} with UUID {} to Context with UUID {}", accessType.getName(), uuid, contextUUID); ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal(); try { @@ -788,16 +839,7 @@ public abstract class ElementManagement { Map affectedInstances = internalAddToContext(targetSecurityContext); - if(honourPropagationConstraintsInContextSharing) { - oDatabaseDocument.commit(); - }else { - if(operationValidator==null) { - throw new ResourceRegistryException("AddFromContext operation which must not honour PropagationConstraints have to provide an " + OperationValidator.class.getSimpleName()); - } - if(operationValidator.isValidOperation(affectedInstances)) { - oDatabaseDocument.commit(); - } - } + oDatabaseDocument.commit(); logger.info("{} with UUID {} successfully added to Context with UUID {}", elementType, uuid, contextUUID); return affectedInstances; @@ -824,12 +866,63 @@ public abstract class ElementManagement { } } - public Map removeFromContext(UUID contextUUID) + public static Map removeFromContextNoPropagationConstraint(Map expectedInstances, UUID contextUUID, boolean dryRun) throws NotFoundException, ContextException, ResourceRegistryException { - return removeFromContext(contextUUID, null); + Set instances = expectedInstances.keySet(); + staticLogger.info("Going to remove {} from Context with UUID {} not following Propagation Constraints", instances, contextUUID); + ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal(); + ODatabaseDocument oDatabaseDocument = null; + try { + oDatabaseDocument = ContextUtility.getAdminSecurityContext().getDatabaseDocument(PermissionMode.WRITER); + oDatabaseDocument.begin(); + + SecurityContext targetSecurityContext = ContextUtility.getInstance().getSecurityContextByUUID(contextUUID); + + Map affectedInstances = new HashMap<>(); + + for(UUID uuid : expectedInstances.keySet()) { + String type = expectedInstances.get(uuid).get(Element.CLASS_PROPERTY).asText(); + ElementManagement elementManagement = ElementManagementUtility.getERManagement(oDatabaseDocument, type); + elementManagement.setUUID(uuid); + elementManagement.setHonourPropagationConstraintsInContextSharing(false); + elementManagement.setDryRunContextSharing(dryRun); + + affectedInstances.putAll(elementManagement.internalRemoveFromContext(targetSecurityContext)); + } + + SharingOperationValidator operationValidator = new SharingOperationValidator(expectedInstances, SharingOperation.REMOVE); + + if(operationValidator.isValidOperation(affectedInstances)) { + oDatabaseDocument.commit(); + } + + staticLogger.info("{} successfully removed from Context with UUID {} not following Propagation Constraints", instances, contextUUID); + + return affectedInstances; + } catch(ResourceRegistryException e) { + staticLogger.error("Unable to remove {} from Context with UUID {} not following Propagation Constraints - Reason is {}", instances, contextUUID, e.getMessage()); + if(oDatabaseDocument != null) { + oDatabaseDocument.rollback(); + } + throw e; + } catch(Exception e) { + staticLogger.error("Unable to remove {} from Context with UUID {} not following Propagation Constraints.", instances, contextUUID, e.getMessage()); + if(oDatabaseDocument != null) { + oDatabaseDocument.rollback(); + } + throw new ContextException(e); + } finally { + if(oDatabaseDocument != null) { + oDatabaseDocument.close(); + } + + if(current!=null) { + current.activateOnCurrentThread(); + } + } } - public Map removeFromContext(UUID contextUUID, OperationValidator operationValidator) + public Map removeFromContext(UUID contextUUID) throws NotFoundException, ContextException, ResourceRegistryException { logger.debug("Going to remove {} with UUID {} from Context with UUID {}", elementType, uuid, contextUUID); ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal(); @@ -841,16 +934,7 @@ public abstract class ElementManagement { Map affectedInstances = internalRemoveFromContext(targetSecurityContext); - if(honourPropagationConstraintsInContextSharing) { - oDatabaseDocument.commit(); - }else { - if(operationValidator==null) { - throw new ResourceRegistryException("RemoveFromContext operation which must not honour PropagationConstraints have to provide an " + OperationValidator.class.getSimpleName()); - } - if(operationValidator.isValidOperation(affectedInstances)) { - oDatabaseDocument.commit(); - } - } + oDatabaseDocument.commit(); logger.info("{} with UUID {} successfully removed from Context with UUID {}", elementType, uuid, contextUUID); return affectedInstances; diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/base/ElementManagementUtility.java b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/base/ElementManagementUtility.java index c48ab16..d97f9db 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/base/ElementManagementUtility.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/base/ElementManagementUtility.java @@ -63,6 +63,29 @@ public class ElementManagementUtility { } + @SuppressWarnings("rawtypes") + public static ElementManagement getERManagement(ODatabaseDocument oDatabaseDocument, String type) throws ResourceRegistryException { + + OClass oClass = ElementManagementUtility.getTypeSchema(oDatabaseDocument, type, null); + ElementManagement erManagement = null; + + if(oClass.isSubClassOf(Resource.NAME)) { + erManagement = new ResourceManagement(); + } else if(oClass.isSubClassOf(Facet.NAME)) { + erManagement = new FacetManagement(); + } else if(oClass.isSubClassOf(ConsistsOf.NAME)) { + erManagement = new ConsistsOfManagement(); + } else if(oClass.isSubClassOf(IsRelatedTo.NAME)) { + erManagement = new IsRelatedToManagement(); + } + + if(erManagement == null) { + throw new ResourceRegistryException(String.format("%s is not querable", type.toString())); + } + + erManagement.setElementType(type); + return erManagement; + } @SuppressWarnings("rawtypes") public static ElementManagement getERManagement(String type) throws ResourceRegistryException { diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/EntityManagement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/EntityManagement.java index ece7a30..42ec772 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/EntityManagement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/EntityManagement.java @@ -208,14 +208,15 @@ public abstract class EntityManagement extends EntityEl * the instance is added in internalAddToContext() function after * the update of Header metadata i.e. modifiedBy, lastUpdateTime */ - - Iterable edges = getElement().getEdges(ODirection.OUT); - - for(OEdge edge : edges) { - RelationManagement relationManagement = getRelationManagement(edge); - relationManagement.setDryRunContextSharing(dryRunContextSharing); - relationManagement.setHonourPropagationConstraintsInContextSharing(honourPropagationConstraintsInContextSharing); - affectedInstances.putAll(relationManagement.internalAddToContext(targetSecurityContext)); + if(honourPropagationConstraintsInContextSharing) { + Iterable edges = getElement().getEdges(ODirection.OUT); + + for(OEdge edge : edges) { + RelationManagement relationManagement = getRelationManagement(edge); + relationManagement.setDryRunContextSharing(dryRunContextSharing); + relationManagement.setHonourPropagationConstraintsInContextSharing(honourPropagationConstraintsInContextSharing); + affectedInstances.putAll(relationManagement.internalAddToContext(targetSecurityContext)); + } } return affectedInstances; diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/rest/SharingManager.java b/src/main/java/org/gcube/informationsystem/resourceregistry/rest/SharingManager.java index ae28e4d..557d047 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/rest/SharingManager.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/rest/SharingManager.java @@ -26,7 +26,6 @@ import org.gcube.informationsystem.resourceregistry.api.rest.SharingPath; import org.gcube.informationsystem.resourceregistry.api.rest.SharingPath.SharingOperation; import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagement; import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagementUtility; -import org.gcube.informationsystem.resourceregistry.instances.model.SharingOperationValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -78,7 +77,7 @@ public class SharingManager { */ @POST @Path("{" + SharingPath.CONTEXTS_PATH_PART + "/{" + AccessPath.CONTEXT_UUID_PATH_PARAM + "}") - public String addRemoveToFromContextNoPropagationConstraint( + public String addRemoveNoPropagationConstraint( @PathParam(AccessPath.CONTEXT_UUID_PATH_PARAM) String contextId, @QueryParam(SharingPath.OPERATION_QUERY_PARAMETER) SharingOperation operation, @QueryParam(SharingPath.DRY_RUN_QUERY_PARAMETER) Boolean dryRun, @@ -110,26 +109,21 @@ public class SharingManager { Map expectedInstances = new HashMap<>(); - ElementManagement elementManagement = null; - boolean first = true; - for(JsonNode node : arrayNode) { + @SuppressWarnings("unused") String type = node.get(Element.CLASS_PROPERTY).asText(); String instanceId = node.get(IdentifiableElement.HEADER_PROPERTY).get(Header.UUID_PROPERTY).asText(); UUID uuid = UUID.fromString(instanceId); expectedInstances.put(uuid, node); - if(first) { - elementManagement = ElementManagementUtility.getERManagement(type); - elementManagement.setUUID(UUID.fromString(instanceId)); - first = false; - } } - elementManagement.setHonourPropagationConstraintsInContextSharing(false); - elementManagement.setDryRunContextSharing(dryRun); UUID contextUUID = UUID.fromString(contextId); - SharingOperationValidator sharingOperationValidator = new SharingOperationValidator(expectedInstances, operation); - Map affectedInstances = elementManagement.addToContext(contextUUID, sharingOperationValidator); + Map affectedInstances = null; + if(operation == SharingOperation.ADD) { + affectedInstances = ElementManagement.addToContextNoPropagationConstraint(expectedInstances, contextUUID, dryRun); + }else { + affectedInstances = ElementManagement.removeFromContextNoPropagationConstraint(expectedInstances, contextUUID, dryRun); + } return serializeAffectedInstaces(objectMapper, affectedInstances); }catch (ResourceRegistryException e) {