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 0bba68c..f4e4066 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 @@ -446,7 +446,11 @@ public abstract class ElementManagement { public boolean internalDelete() throws NotFoundException, ResourceRegistryException { setOperation(Operation.DELETE); - return reallyDelete(); + boolean deleted = reallyDelete(); + if(deleted) { + sanityCheck(); + } + return deleted; } public void setElement(El element) throws ResourceRegistryException { @@ -1111,14 +1115,15 @@ public abstract class ElementManagement { return superClasses; } */ - - public boolean isAvailableOnContext(OElement element, SecurityContext securityContext) { + /* + public boolean isAvailableOnContext(SecurityContext securityContext) { try { return securityContext.isElementInContext(element); } catch (ResourceRegistryException e) { return false; } } + */ protected String getNotNullErrorMessage(String fieldName) { StringBuffer stringBuffer = new StringBuffer(); diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/FacetManagement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/FacetManagement.java index 80fd9fe..3a493b6 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/FacetManagement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/FacetManagement.java @@ -1,11 +1,15 @@ package org.gcube.informationsystem.resourceregistry.instances.model.entities; +import java.util.Map; +import java.util.UUID; + import org.gcube.com.fasterxml.jackson.databind.JsonNode; import org.gcube.informationsystem.base.reference.AccessType; import org.gcube.informationsystem.model.reference.entities.Facet; import org.gcube.informationsystem.resourceregistry.api.exceptions.AlreadyPresentException; import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException; import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; +import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextException; import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.facet.FacetAlreadyPresentException; import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.facet.FacetAvailableInAnotherContextException; import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.facet.FacetNotFoundException; @@ -23,6 +27,8 @@ import com.orientechnologies.orient.core.record.OVertex; */ public class FacetManagement extends EntityManagement { + protected ResourceManagement resourceManagement; + public FacetManagement() { super(AccessType.FACET); } @@ -60,9 +66,25 @@ public class FacetManagement extends EntityManagement { return facet; } + @Override + protected Map reallyRemoveFromContext() + throws ContextException, ResourceRegistryException { + if(entryPoint) { + OVertex oVertex = getElement().getVertices(ODirection.IN).iterator().next(); + resourceManagement = new ResourceManagement(); + resourceManagement.setElement(oVertex); + } + return super.reallyRemoveFromContext(); + } + @Override protected boolean reallyDelete() throws FacetNotFoundException, ResourceRegistryException { - getElement().delete(); + if(entryPoint) { + OVertex oVertex = getElement().getVertices(ODirection.IN).iterator().next(); + resourceManagement = new ResourceManagement(); + resourceManagement.setElement(oVertex); + } + element.delete(); return true; } @@ -85,9 +107,11 @@ public class FacetManagement extends EntityManagement { } ODatabaseDocument targetSecurityContextODatabaseDocument = null; try { - OVertex oVertex = getElement().getVertices(ODirection.IN).iterator().next(); - ResourceManagement resourceManagement = new ResourceManagement(); - resourceManagement.setElement(oVertex); + if(resourceManagement==null) { + OVertex oVertex = getElement().getVertices(ODirection.IN).iterator().next(); + ResourceManagement resourceManagement = new ResourceManagement(); + resourceManagement.setElement(oVertex); + } switch (operation) { case CREATE: case DELETE: resourceManagement.setWorkingContext(getWorkingContext()); @@ -108,6 +132,8 @@ public class FacetManagement extends EntityManagement { resourceManagement.setOperation(operation); resourceManagement.sanityCheck(); + }catch (ResourceRegistryException e) { + throw e; }catch (Exception e) { throw new ResourceRegistryException(e); }finally { diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/ResourceManagement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/ResourceManagement.java index 419c23b..e542040 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/ResourceManagement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/ResourceManagement.java @@ -15,6 +15,7 @@ import org.gcube.informationsystem.model.reference.entities.Facet; import org.gcube.informationsystem.model.reference.entities.Resource; import org.gcube.informationsystem.model.reference.relations.ConsistsOf; import org.gcube.informationsystem.model.reference.relations.IsRelatedTo; +import org.gcube.informationsystem.resourceregistry.api.exceptions.AvailableInAnotherContextException; import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException; import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextException; @@ -25,6 +26,7 @@ import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.Schema import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaViolationException; import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext.PermissionMode; import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagementUtility; +import org.gcube.informationsystem.resourceregistry.instances.model.Operation; import org.gcube.informationsystem.resourceregistry.instances.model.relations.ConsistsOfManagement; import org.gcube.informationsystem.resourceregistry.instances.model.relations.IsRelatedToManagement; import org.gcube.informationsystem.resourceregistry.instances.model.relations.RelationManagement; @@ -391,6 +393,10 @@ public class ResourceManagement extends EntityManagement */ @Override public void sanityCheck() throws SchemaViolationException, ResourceRegistryException { + if(entryPoint && operation == Operation.DELETE) { + return; + } + TypesCache typesCache = TypesCache.getInstance(); Set consistsOfFacetConstraints = getResourceTypeConstraint(); @@ -400,10 +406,75 @@ public class ResourceManagement extends EntityManagement Iterable edges = getElement().getEdges(ODirection.OUT); for(OEdge edge : edges) { - RelationManagement relationManagement = getRelationManagement(edge); - if(!(relationManagement instanceof ConsistsOfManagement)) { - continue; + + String id = edge.getIdentity().toString(); + RelationManagement relationManagement = relationManagements.get(id); + + if(entryPoint) { + + switch (operation) { + case ADD_TO_CONTEXT: + if(relationManagement == null) { + try { + relationManagement = ElementManagementUtility.getRelationManagement(targetSecurityContext, oDatabaseDocument, edge); + relationManagements.put(id, relationManagement); + }catch (AvailableInAnotherContextException e) { + continue; + } + }else { + /* + * The relation has been already managed in add to context so it has been added to the targetSecurityContext. + * The transaction is not yet committed so we need to consider as part of context without trying to load from + * DB with dedicated security connection. + */ + } + break; + + case REMOVE_FROM_CONTEXT: + if(relationManagement != null) { + /* + * The relation has been removed from the targetContext but it has not been committed. + * We must consider as not available in targetSecurityContext + */ + continue; + }else { + relationManagement = ElementManagementUtility.getRelationManagement(targetSecurityContext, oDatabaseDocument, edge); + relationManagements.put(id, relationManagement); + } + break; + + case CREATE: case UPDATE: + + if(relationManagement == null) { + relationManagement = ElementManagementUtility.getRelationManagement(getWorkingContext(), oDatabaseDocument, edge); + relationManagements.put(id, relationManagement); + /* + * Here the AvailableInAnotherContextException should not occur because the connection to the DB is with the + * context role and not with admin as in addToContext/removeFromContext + */ + }else { + /* + * During create and update the relation could be still not be in the context because the + * transaction is still to be committed. We use the pending instance of relation management + * to evaluate the instance. + */ + } + break; + + default: + break; + } + }else { + if(relationManagement==null) { + relationManagement = getRelationManagement(edge); + } } + + if(!(relationManagement instanceof ConsistsOfManagement)) { + continue; + } + + String consistsOfType = relationManagement.getTypeName(); String facetType = relationManagement.getTargetEntityManagement().getTypeName(); diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/relations/ConsistsOfManagement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/relations/ConsistsOfManagement.java index 943fe79..2f0a750 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/relations/ConsistsOfManagement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/relations/ConsistsOfManagement.java @@ -109,16 +109,16 @@ public class ConsistsOfManagement extends RelationManagement affectedInstances = new HashMap<>(); RemoveConstraint removeConstraint = RemoveConstraint.keep; @@ -733,6 +735,8 @@ public abstract class RelationManagement isIdentifiedBy = (IsIdentifiedBy) createEService.getConsistsOf(IsIdentifiedBy.class).get(0); + ConsistsOfManagement consistsOfManagement = new ConsistsOfManagement(); + consistsOfManagement.setElementType(IsIdentifiedBy.NAME); + consistsOfManagement.setUUID(isIdentifiedBy.getHeader().getUUID()); + + try { + consistsOfManagement.delete(); + throw new Exception("You should not be able to delete a mandatory ConsistsOf"); + }catch (SchemaViolationException e) { + // As expected + }catch (Exception e) { + resourceManagement.delete(); + throw e; + } + + SoftwareFacet softwareFacet = isIdentifiedBy.getTarget(); + FacetManagement facetManagement = new FacetManagement(); + facetManagement.setElementType(SoftwareFacet.NAME); + facetManagement.setUUID(softwareFacet.getHeader().getUUID()); + + try { + facetManagement.delete(); + throw new Exception("You should not be able to delete a mandatory Facet"); + }catch (SchemaViolationException e) { + // As expected + }catch (Exception e) { + resourceManagement.delete(); + throw e; + } + + resourceManagement.delete(); + + } + + + @Test + public void testCreateEServiceAndRemoveFromContextRequiredFacet() throws Exception { + EService eService = instantiateValidEService(); + ResourceManagement resourceManagement = new ResourceManagement(); + resourceManagement.setElementType(EService.NAME); + resourceManagement.setJson(ElementMapper.marshal(eService)); + String createEServiceString = resourceManagement.create(); + EService createEService = ElementMapper.unmarshal(EService.class, createEServiceString); + + @SuppressWarnings("unchecked") + IsIdentifiedBy isIdentifiedBy = (IsIdentifiedBy) createEService.getConsistsOf(IsIdentifiedBy.class).get(0); + ConsistsOfManagement consistsOfManagement = new ConsistsOfManagement(); + consistsOfManagement.setElementType(IsIdentifiedBy.NAME); + consistsOfManagement.setUUID(isIdentifiedBy.getHeader().getUUID()); + + try { + consistsOfManagement.removeFromContext(ContextUtility.getCurrentSecurityContext().getUUID()); + throw new Exception("You should not be able to delete a mandatory ConsistsOf"); + }catch (SchemaViolationException e) { + // As expected + }catch (Exception e) { + resourceManagement.delete(); + throw e; + } + + SoftwareFacet softwareFacet = isIdentifiedBy.getTarget(); + FacetManagement facetManagement = new FacetManagement(); + facetManagement.setElementType(SoftwareFacet.NAME); + facetManagement.setUUID(softwareFacet.getHeader().getUUID()); + + try { + facetManagement.removeFromContext(ContextUtility.getCurrentSecurityContext().getUUID()); + throw new Exception("You should not be able to delete a mandatory Facet"); + }catch (SchemaViolationException e) { + // As expected + }catch (Exception e) { + resourceManagement.delete(); + throw e; + } + + resourceManagement.delete(); + + } @Test public void testCreateFacetWithAdditionlEncryptedField() throws Exception { 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 1ce15f2..f3b5750 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 @@ -12,7 +12,6 @@ import org.gcube.common.authorization.client.exceptions.ObjectNotFound; import org.gcube.informationsystem.base.reference.IdentifiableElement; import org.gcube.informationsystem.context.reference.entities.Context; import org.gcube.informationsystem.model.impl.properties.PropagationConstraintImpl; -import org.gcube.informationsystem.model.reference.entities.Facet; import org.gcube.informationsystem.model.reference.properties.PropagationConstraint; import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.AddConstraint; import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.RemoveConstraint; @@ -35,15 +34,10 @@ import org.gcube.informationsystem.resourceregistry.instances.model.entities.Res import org.gcube.informationsystem.resourceregistry.instances.model.relations.IsRelatedToManagement; import org.gcube.informationsystem.utils.ElementMapper; import org.gcube.resourcemanagement.model.impl.entities.facets.CPUFacetImpl; -import org.gcube.resourcemanagement.model.impl.entities.facets.SoftwareFacetImpl; -import org.gcube.resourcemanagement.model.impl.entities.resources.EServiceImpl; -import org.gcube.resourcemanagement.model.impl.relations.consistsof.IsIdentifiedByImpl; import org.gcube.resourcemanagement.model.impl.relations.isrelatedto.ActivatesImpl; import org.gcube.resourcemanagement.model.reference.entities.facets.CPUFacet; -import org.gcube.resourcemanagement.model.reference.entities.facets.SoftwareFacet; import org.gcube.resourcemanagement.model.reference.entities.resources.EService; import org.gcube.resourcemanagement.model.reference.entities.resources.HostingNode; -import org.gcube.resourcemanagement.model.reference.relations.consistsof.IsIdentifiedBy; import org.gcube.resourcemanagement.model.reference.relations.isrelatedto.Activates; import org.junit.Assert; import org.junit.Test;