From b18ebe74271bd1bb8956cd072c4f5ea07a88983d Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Tue, 2 Feb 2021 16:50:48 +0100 Subject: [PATCH] Implementing strategy for add/remove to/from context no follow --- .../contexts/security/SecurityContext.java | 17 ++++++++ .../instances/base/ElementManagement.java | 41 ++++++++++++++++++- .../model/entities/EntityManagement.java | 16 ++++---- .../resourceregistry/rest/SharingManager.java | 29 +++++++------ 4 files changed, 82 insertions(+), 21 deletions(-) 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 7c83185..d1d46c8 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 @@ -28,6 +28,7 @@ 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.id.ORID; import com.orientechnologies.orient.core.metadata.security.ORestrictedOperation; import com.orientechnologies.orient.core.metadata.security.ORole; import com.orientechnologies.orient.core.metadata.security.OSecurity; @@ -322,6 +323,22 @@ public class SecurityContext { oSecurity.allowRole(oDocument, ORestrictedOperation.ALLOW_READ, readerRoleName); } + public boolean isElementInContext(final OElement element) throws ResourceRegistryException { + ORID orid = element.getIdentity(); + + ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal(); + ODatabaseDocument contextODatabaseDocument = getDatabaseDocument(PermissionMode.READER); + contextODatabaseDocument.activateOnCurrentThread(); + + ORecord oRecord = contextODatabaseDocument.getRecord(orid); + logger.trace("{}", oRecord); + + if(current!=null) { + current.activateOnCurrentThread(); + } + return true; + } + public void addElement(OElement element, ODatabaseDocument oDatabaseDocument) { ODocument oDocument = element.getRecord(); OSecurity oSecurity = getOSecurity(oDatabaseDocument); 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 a36320b..9df5070 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 @@ -42,6 +42,7 @@ import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityCo 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.utils.HeaderOrient; import org.gcube.informationsystem.resourceregistry.utils.HeaderUtility; import org.gcube.informationsystem.resourceregistry.utils.Utility; @@ -772,6 +773,11 @@ public abstract class ElementManagement { public Map addToContext(UUID contextUUID) throws NotFoundException, ContextException, ResourceRegistryException { + return addToContext(contextUUID, null); + } + + public Map addToContext(UUID contextUUID, OperationValidator operationValidator) + throws NotFoundException, ContextException, ResourceRegistryException { logger.info("Going to add {} with UUID {} to Context with UUID {}", accessType.getName(), uuid, contextUUID); ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal(); try { @@ -782,7 +788,16 @@ public abstract class ElementManagement { Map affectedInstances = internalAddToContext(targetSecurityContext); - oDatabaseDocument.commit(); + if(honourPropagationConstraintsInContextSharing) { + oDatabaseDocument.commit(); + }else { + if(operationValidator==null) { + throw new ResourceRegistryException("A removeFromContext operation which must not honour PropagationConstraints have to provide an " + OperationValidator.class.getSimpleName()); + } + if(operationValidator.isValidOperation(affectedInstances)) { + oDatabaseDocument.commit(); + } + } logger.info("{} with UUID {} successfully added to Context with UUID {}", elementType, uuid, contextUUID); return affectedInstances; @@ -811,6 +826,11 @@ public abstract class ElementManagement { public Map removeFromContext(UUID contextUUID) throws NotFoundException, ContextException, ResourceRegistryException { + return removeFromContext(contextUUID, null); + } + + public Map removeFromContext(UUID contextUUID, OperationValidator operationValidator) + throws NotFoundException, ContextException, ResourceRegistryException { logger.debug("Going to remove {} with UUID {} from Context with UUID {}", elementType, uuid, contextUUID); ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal(); try { @@ -821,7 +841,16 @@ public abstract class ElementManagement { Map affectedInstances = internalRemoveFromContext(targetSecurityContext); - oDatabaseDocument.commit(); + if(honourPropagationConstraintsInContextSharing) { + oDatabaseDocument.commit(); + }else { + if(operationValidator==null) { + throw new ResourceRegistryException("A removeFromContext operation which must not honour PropagationConstraints have to provide an " + OperationValidator.class.getSimpleName()); + } + if(operationValidator.isValidOperation(affectedInstances)) { + oDatabaseDocument.commit(); + } + } logger.info("{} with UUID {} successfully removed from Context with UUID {}", elementType, uuid, contextUUID); return affectedInstances; @@ -1219,4 +1248,12 @@ public abstract class ElementManagement { } } + public boolean isAvailableOnContext(OElement element, SecurityContext securityContext) { + try { + return securityContext.isElementInContext(element); + } catch (ResourceRegistryException e) { + return false; + } + } + } 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 e1704a8..ece7a30 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 @@ -227,13 +227,15 @@ public abstract class EntityManagement extends EntityEl Map affectedInstances = new HashMap<>(); - Iterable edges = getElement().getEdges(ODirection.OUT); - - for(OEdge edge : edges) { - RelationManagement relationManagement = getRelationManagement(edge); - relationManagement.setDryRunContextSharing(dryRunContextSharing); - relationManagement.setHonourPropagationConstraintsInContextSharing(honourPropagationConstraintsInContextSharing); - affectedInstances.putAll(relationManagement.internalRemoveFromContext(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.internalRemoveFromContext(targetSecurityContext)); + } } if(!dryRunContextSharing) { 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 10b64c5..c34e34f 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/rest/SharingManager.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/rest/SharingManager.java @@ -105,25 +105,30 @@ public class SharingManager { CalledMethodProvider.instance.set(calledMethod.toString()); ObjectMapper objectMapper = new ObjectMapper(); - Map affectedInstances = new HashMap<>(); - ArrayNode arrayNode = (ArrayNode) objectMapper.readTree(body); - for(JsonNode node : arrayNode) { + Map expectedInstances = new HashMap<>(); + + ElementManagement elementManagement = null; + boolean first = true; + + for(JsonNode node : arrayNode) { String type = node.get(Element.CLASS_PROPERTY).asText(); String instanceId = node.get(IdentifiableElement.HEADER_PROPERTY).get(Header.UUID_PROPERTY).asText(); - - ElementManagement elementManagement = ElementManagementUtility.getERManagement(type); - elementManagement.setUUID(UUID.fromString(instanceId)); - elementManagement.setDryRunContextSharing(dryRun); - - if(operation == SharingOperation.ADD) { - affectedInstances.putAll(elementManagement.addToContext(UUID.fromString(contextId))); - }else { - affectedInstances.putAll(elementManagement.removeFromContext(UUID.fromString(contextId))); + 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); + Map affectedInstances = elementManagement.addToContext(contextUUID); + return serializeAffectedInstaces(objectMapper, affectedInstances); }catch (ResourceRegistryException e) { throw e;