Add to Context deny to add a resource without adding at least a facet.

Added a test to check the service behave properly
This commit is contained in:
Luca Frosini 2021-01-27 21:57:06 +01:00
parent 376fbd1df6
commit 27cec7ec31
3 changed files with 216 additions and 7 deletions

View File

@ -780,7 +780,7 @@ public abstract class ElementManagement<El extends OElement> {
return affectedInstances;
} catch(ResourceRegistryException e) {
logger.error("Unable to add {} with UUID {} to Context with UUID {}", elementType, uuid, contextUUID);
logger.error("Unable to add {} with UUID {} to Context with UUID {} - Cause is {}", elementType, uuid, contextUUID, e.getMessage());
if(oDatabaseDocument != null) {
oDatabaseDocument.rollback();
}

View File

@ -1,14 +1,20 @@
package org.gcube.informationsystem.resourceregistry.instances.model.entities;
import java.util.HashMap;
import java.util.Iterator;
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.context.reference.entities.Context;
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.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.resource.ResourceAlreadyPresentException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resource.ResourceAvailableInAnotherContextException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resource.ResourceNotFoundException;
@ -224,6 +230,54 @@ public class ResourceManagement extends EntityManagement<Resource> {
return true;
}
@Override
protected Map<UUID,JsonNode> reallyAddToContext(SecurityContext targetSecurityContext)
throws ContextException, ResourceRegistryException {
Map<UUID,JsonNode> affectedInstances = new HashMap<>();
if(!dryRunContextSharing) {
targetSecurityContext.addElement(getElement(), oDatabaseDocument);
}
/*
* DO NOT UNCOMMENT
* // affectedInstances.put(uuid, serializeSelfOnly());
* the instance is added in internalAddToContext() function after
* the update of Header metadata i.e. modifiedBy, lastUpdateTime
*/
Iterable<OEdge> edges = getElement().getEdges(ODirection.OUT);
int facetCounter = 0;
for(OEdge edge : edges) {
RelationManagement<?> relationManagement = getRelationManagement(edge);
relationManagement.setDryRunContextSharing(dryRunContextSharing);
relationManagement.setHonourPropagationConstraintsInContextSharing(honourPropagationConstraintsInContextSharing);
Map<UUID,JsonNode> resourceCharacterisationInstances = relationManagement.internalAddToContext(targetSecurityContext);
if(relationManagement instanceof ConsistsOfManagement) {
facetCounter = facetCounter + resourceCharacterisationInstances.size();
}
affectedInstances.putAll(resourceCharacterisationInstances);
}
if(facetCounter == 0) {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("Any ");
stringBuffer.append(Resource.NAME);
stringBuffer.append(" must ");
stringBuffer.append(ConsistsOf.NAME);
stringBuffer.append(" at least of one ");
stringBuffer.append(Facet.NAME);
stringBuffer.append(" in any ");
stringBuffer.append(Context.NAME);
throw new ResourceRegistryException(stringBuffer.toString());
}
return affectedInstances;
}
public String all(boolean polymorphic) throws ResourceRegistryException {
try {
oDatabaseDocument = getWorkingContext().getDatabaseDocument(PermissionMode.READER);

View File

@ -23,6 +23,7 @@ import org.gcube.informationsystem.base.reference.IdentifiableElement;
import org.gcube.informationsystem.context.reference.entities.Context;
import org.gcube.informationsystem.model.impl.properties.HeaderImpl;
import org.gcube.informationsystem.model.impl.properties.PropagationConstraintImpl;
import org.gcube.informationsystem.model.reference.entities.Entity;
import org.gcube.informationsystem.model.reference.entities.Facet;
import org.gcube.informationsystem.model.reference.entities.Resource;
import org.gcube.informationsystem.model.reference.properties.Header;
@ -31,6 +32,7 @@ import org.gcube.informationsystem.model.reference.properties.PropagationConstra
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.RemoveConstraint;
import org.gcube.informationsystem.model.reference.relations.ConsistsOf;
import org.gcube.informationsystem.model.reference.relations.IsRelatedTo;
import org.gcube.informationsystem.model.reference.relations.Relation;
import org.gcube.informationsystem.resourceregistry.ContextTest;
import org.gcube.informationsystem.resourceregistry.api.contexts.ContextCache;
import org.gcube.informationsystem.resourceregistry.api.contexts.ContextCacheRenewal;
@ -88,6 +90,8 @@ import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.orientechnologies.orient.core.record.ODirection;
/**
* @author Luca Frosini (ISTI - CNR)
*/
@ -188,12 +192,161 @@ public class BasicTest extends ContextTest {
Assert.assertTrue(deleted);
}
// TODO test add to context to a resource with only one facet and add propagation constraint to unpropagate.
// TODO test remove from context to a facet which is the only facet that characterise a Resource.
@Test(expected = ResourceRegistryException.class)
public void testResourceWithOnlyOneFacet() throws Exception {
EService eService = new EServiceImpl();
SoftwareFacet softwareFacet = new SoftwareFacetImpl();
softwareFacet.setGroup("InformationSystem");
softwareFacet.setName("resource-registry");
softwareFacet.setVersion("1.1.0");
PropagationConstraint propagationConstraint = new PropagationConstraintImpl();
propagationConstraint.setAddConstraint(AddConstraint.unpropagate);
propagationConstraint.setRemoveConstraint(RemoveConstraint.cascade);
IsIdentifiedBy<EService, Facet> isIdentifiedBy = new IsIdentifiedByImpl<EService, Facet>(
eService, softwareFacet, propagationConstraint);
eService.addFacet(isIdentifiedBy);
ResourceManagement resourceManagement = new ResourceManagement();
resourceManagement.setElementType(EService.NAME);
resourceManagement.setJson(ElementMapper.marshal(eService));
String json = resourceManagement.create();
logger.debug("Created : {}", json);
eService = ElementMapper.unmarshal(EService.class, json);
logger.debug("Unmarshalled {} {}", EService.NAME, eService);
/*------------------------------------------------------------------------*/
logger.debug("Switching to another context");
ContextTest.setContextByName(ALTERNATIVE_TEST_SCOPE);
try {
addToContextThenTestIfBehaveProperly(eService, true);
}finally {
UUID eServiceUUID = eService.getHeader().getUUID();
resourceManagement = new ResourceManagement();
resourceManagement.setUUID(eServiceUUID);
boolean deleted = resourceManagement.delete();
Assert.assertTrue(deleted);
}
}
protected Map<UUID, Element> getAddedExpectedInstances(Resource r) {
protected Map<UUID, Element> getRemovedExpectedInstances(Resource r) {
Map<UUID, Element> expected = new HashMap<>();
expected.put(r.getHeader().getUUID(), r);
// TODO query
for(IsRelatedTo<? extends Resource, ? extends Resource> isRelatedTo : r.getIsRelatedTo()) {
// TODO
if(isRelatedTo.getPropagationConstraint().getRemoveConstraint() == RemoveConstraint.cascade) {
expected.put(isRelatedTo.getHeader().getUUID(), isRelatedTo);
expected.putAll(getRemovedExpectedInstances(isRelatedTo.getTarget()));
// TODO
}
if(isRelatedTo.getPropagationConstraint().getRemoveConstraint() == RemoveConstraint.cascadeWhenOrphan) {
expected.put(isRelatedTo.getHeader().getUUID(), isRelatedTo);
expected.putAll(getRemovedExpectedInstances(isRelatedTo.getTarget()));
// TODO
// TODO
}
}
for(ConsistsOf<? extends Resource, ? extends Facet> consistsOf : r.getConsistsOf()) {
if(consistsOf.getPropagationConstraint().getRemoveConstraint() == RemoveConstraint.cascade || consistsOf.getPropagationConstraint().getRemoveConstraint() == RemoveConstraint.cascadeWhenOrphan ) {
expected.put(consistsOf.getHeader().getUUID(), consistsOf);
Facet facet = consistsOf.getTarget();
expected.put(facet.getHeader().getUUID(), facet);
}
}
return expected;
}
protected void removeFromContextThenTestIfBehaveProperly(Resource r, boolean dryRun) throws ResourceRegistryException {
Map<UUID, Element> expectedInstances = getRemovedExpectedInstances(r);
ResourceManagement resourceManagement = new ResourceManagement();
resourceManagement.setElementType(TypeMapper.getType(r.getClass()));
resourceManagement.setUUID(r.getHeader().getUUID());
resourceManagement.setDryRunContextSharing(dryRun);
UUID contextUUID = ContextUtility.getCurrentSecurityContext().getUUID();
Map<UUID, JsonNode> affectedInstances = resourceManagement.removeFromContext(contextUUID);
SortedSet<UUID> expectedInstancesUUID = new TreeSet<>(expectedInstances.keySet());
SortedSet<UUID> affectedInstancesUUID = new TreeSet<>(affectedInstances.keySet());
logger.trace("Expected Instances are {} : {}", expectedInstancesUUID.size(), expectedInstancesUUID);
logger.trace("Affected Instances are {} : {}", affectedInstancesUUID.size(), affectedInstancesUUID);
Assert.assertTrue(expectedInstancesUUID.size()==affectedInstancesUUID.size());
Assert.assertTrue(expectedInstancesUUID.containsAll(affectedInstancesUUID));
Assert.assertTrue(affectedInstancesUUID.containsAll(expectedInstancesUUID));
for(UUID uuid : affectedInstances.keySet()) {
Element element = expectedInstances.get(uuid);
String expectedType = TypeMapper.getType(element.getClass());
JsonNode affectedJsonNode = affectedInstances.get(uuid);
String affectedType = affectedJsonNode.get(Element.CLASS_PROPERTY).asText();
Assert.assertTrue(affectedType.compareTo(expectedType)==0);
}
}
interface RelationConstraint {
public boolean mustBeAdded(Relation<Resource, Entity> r);
}
protected Resource getAndAddIsRelatedTo(Resource r, RelationConstraint relationConstraint) throws ResourceRegistryException, Exception {
ResourceManagement resourceManagement = new ResourceManagement();
String resourceType = TypeMapper.getType(r);
// resourceManagement.setElementType(resourceType);
UUID resourceUUID = r.getHeader().getUUID();
// resourceManagement.setUUID(resourceUUID);
String ret = resourceManagement.query(IsRelatedTo.NAME, resourceType, resourceUUID, ODirection.OUT, true, new HashMap<>());
@SuppressWarnings("rawtypes")
List<IsRelatedTo> isRelatedToList = ElementMapper.unmarshalList(IsRelatedTo.class, ret);
for(@SuppressWarnings("rawtypes") IsRelatedTo isRelatedTo : isRelatedToList) {
@SuppressWarnings("unchecked")
boolean mustBeAdded = relationConstraint.mustBeAdded(isRelatedTo);
if(mustBeAdded) {
@SuppressWarnings("unchecked")
IsRelatedTo<EService, Resource> irt = (IsRelatedTo<EService, Resource>) isRelatedTo;
r.attachResource(irt);
}
}
return r;
}
protected Map<UUID, Element> getAddedExpectedInstances(Resource r) throws ResourceRegistryException, Exception {
Map<UUID, Element> expected = new HashMap<>();
expected.put(r.getHeader().getUUID(), r);
RelationConstraint propagateConstraint = new RelationConstraint() {
@Override
public boolean mustBeAdded(Relation<Resource, Entity> r) {
return r.getPropagationConstraint().getAddConstraint() == AddConstraint.propagate;
}
};
r = getAndAddIsRelatedTo(r, propagateConstraint);
for(IsRelatedTo<? extends Resource, ? extends Resource> isRelatedTo : r.getIsRelatedTo()) {
if(isRelatedTo.getPropagationConstraint().getAddConstraint() == AddConstraint.propagate) {
expected.put(isRelatedTo.getHeader().getUUID(), isRelatedTo);
@ -210,10 +363,11 @@ public class BasicTest extends ContextTest {
return expected;
}
protected void addToContextThenTestIfBehaveProperly(Resource r, boolean dryRun) throws ResourceRegistryException {
protected void addToContextThenTestIfBehaveProperly(Resource r, boolean dryRun) throws ResourceRegistryException, Exception {
Map<UUID, Element> expectedInstances = getAddedExpectedInstances(r);
ResourceManagement resourceManagement = new ResourceManagement();
resourceManagement.setElementType(TypeMapper.getType(r));
resourceManagement.setUUID(r.getHeader().getUUID());
resourceManagement.setDryRunContextSharing(dryRun);
UUID contextUUID = ContextUtility.getCurrentSecurityContext().getUUID();
@ -361,6 +515,7 @@ public class BasicTest extends ContextTest {
hostingNodeInstances.put(consistsOf.getTarget().getHeader().getUUID(), consistsOf.getTarget());
}
/*
IsRelatedToManagement isRelatedToManagement = new IsRelatedToManagement();
isRelatedToManagement.setElementType(Activates.NAME);
isRelatedToManagement.setUUID(activatedUUID);
@ -373,11 +528,11 @@ public class BasicTest extends ContextTest {
activates = unmarshalledActivates;
hostingNode.attachResource(activates);
*/
/* ------------------------------------------------------------------ */
logger.debug("Switching to another scope");
logger.debug("Switching to another context");
ContextTest.setContextByName(ALTERNATIVE_TEST_SCOPE);
addToContextThenTestIfBehaveProperly(hostingNode, true);