Including contexts in the instances header when requested #20012

This commit is contained in:
Luca Frosini 2020-11-09 15:45:07 +01:00
parent 33ae3ed356
commit 18cd7e167e
12 changed files with 325 additions and 22 deletions

View File

@ -3,7 +3,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
# Changelog for Resource Registry Service
## [v4.0.0-SNAPSHOT] [r5.0.0] -
## [v4.0.0-SNAPSHOT]
- Switched JSON management to gcube-jackson [#19116]

View File

@ -32,7 +32,7 @@
<dependency>
<groupId>org.gcube.distribution</groupId>
<artifactId>gcube-smartgears-bom</artifactId>
<version>2.0.0-SNAPSHOT</version>
<version>2.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -43,7 +43,6 @@
<dependency>
<groupId>org.gcube.information-system</groupId>
<artifactId>resource-registry-api</artifactId>
<version>[4.1.0-SNAPSHOT, 5.0.0-SNAPSHOT)</version>
<scope>provided</scope>
</dependency>
<dependency>

View File

@ -67,6 +67,20 @@ public class ContextUtility {
return hierarchicalMode;
}
private static final InheritableThreadLocal<Boolean> includeInstanceContexts = new InheritableThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return false;
}
};
public static InheritableThreadLocal<Boolean> getIncludeInstanceContexts() {
return includeInstanceContexts;
}
private static String getCurrentContextFullName() {
String token = SecurityTokenProvider.instance.get();
AuthorizationEntry authorizationEntry = null;
@ -129,7 +143,7 @@ public class ContextUtility {
} catch(ContextException e) {
throw e;
} catch(Exception e) {
throw new ContextException("Unable to restrive Context UUID from current Context", e);
throw new ContextException("Unable to retrieve Context UUID from current Context", e);
}
}

View File

@ -761,7 +761,7 @@ public abstract class ElementManagement<El extends OElement> {
}
}
public String getContexts() throws NotFoundException, ContextException, ResourceRegistryException {
public Set<String> getContextsSet() throws NotFoundException, ContextException, ResourceRegistryException {
logger.debug("Going to get contexts for {} with UUID", elementType, uuid);
ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
try {
@ -769,12 +769,7 @@ public abstract class ElementManagement<El extends OElement> {
oDatabaseDocument = adminSecurityContext.getDatabaseDocument(PermissionMode.READER);
Set<String> contexts = SecurityContext.getContexts(getElement());
ObjectMapper objectMapper = new ObjectMapper();
ArrayNode arrayNode = objectMapper.createArrayNode();
for(String contextUUID : contexts) {
arrayNode.add(contextUUID);
}
return objectMapper.writeValueAsString(arrayNode);
return contexts;
} catch(ResourceRegistryException e) {
logger.error("Unable to get contexts for {} with UUID {}", elementType, uuid, e);
throw e;
@ -792,6 +787,33 @@ public abstract class ElementManagement<El extends OElement> {
}
}
public String getContexts() throws NotFoundException, ContextException, ResourceRegistryException {
try {
ObjectMapper objectMapper = new ObjectMapper();
ArrayNode arrayNode = getContextsAsArrayNode(objectMapper);
return objectMapper.writeValueAsString(arrayNode);
} catch(ResourceRegistryException e) {
throw e;
} catch (Exception e) {
throw new ContextException(e);
}
}
public ArrayNode getContextsAsArrayNode(ObjectMapper objectMapper) throws NotFoundException, ContextException, ResourceRegistryException {
try {
Set<String> contexts = getContextsSet();
ArrayNode arrayNode = objectMapper.createArrayNode();
for(String contextUUID : contexts) {
arrayNode.add(contextUUID);
}
return arrayNode;
} catch(ResourceRegistryException e) {
throw e;
} catch (Exception e) {
throw new ContextException(e);
}
}
public static String getClassProperty(JsonNode jsonNode) {
if(jsonNode.has(Element.CLASS_PROPERTY)) {
return jsonNode.get(Element.CLASS_PROPERTY).asText();
@ -990,7 +1012,11 @@ public abstract class ElementManagement<El extends OElement> {
if(key.compareTo(IdentifiableElement.HEADER_PROPERTY) == 0) {
// Keeping the header
HeaderOrient headerOrient = HeaderUtility.getHeaderOrient((ODocument) object);
return Utility.toJsonNode(headerOrient, false);
JsonNode headerJson = Utility.toJsonNode(headerOrient, false);
if(ContextUtility.getIncludeInstanceContexts().get()) {
((ObjectNode) headerJson).set(Header.__CONTEXTS, getContextsAsArrayNode(objectMapper));
}
return headerJson;
}
if(ignoreKeys.contains(key)) {

View File

@ -178,7 +178,8 @@ public class Access extends BaseRest {
@QueryParam(AccessPath.POLYMORPHIC_PARAM) @DefaultValue("true") Boolean polymorphic)
throws NotFoundException, ResourceRegistryException {
logger.info("Requested all {}instances of {}", polymorphic ? AccessPath.POLYMORPHIC_PARAM + " " : "", type);
setHierarchicalMode();
checkHierarchicalMode();
checkIncludeInstancesContexts();
/*
List<String> pathValues = new ArrayList<>();
pathValues.add(AccessPath.INSTANCES_PATH_PART);
@ -206,8 +207,8 @@ public class Access extends BaseRest {
public Response instanceExists(@PathParam(AccessPath.TYPE_PATH_PARAM) String type,
@PathParam(AccessPath.UUID_PATH_PARAM) String uuid) throws NotFoundException, ResourceRegistryException {
logger.info("Requested to check if {} with id {} exists", type, uuid);
setHierarchicalMode();
checkHierarchicalMode();
checkIncludeInstancesContexts();
/*
List<String> pathValues = new ArrayList<>();
pathValues.add(AccessPath.INSTANCES_PATH_PART);
@ -251,7 +252,8 @@ public class Access extends BaseRest {
public String getInstance(@PathParam(AccessPath.TYPE_PATH_PARAM) String type,
@PathParam(AccessPath.UUID_PATH_PARAM) String uuid) throws NotFoundException, ResourceRegistryException {
logger.info("Requested to read {} with id {}", type, uuid);
setHierarchicalMode();
checkHierarchicalMode();
checkIncludeInstancesContexts();
/*
List<String> pathValues = new ArrayList<>();
@ -301,7 +303,8 @@ public class Access extends BaseRest {
@QueryParam(AccessPath.RAW_PARAM) @DefaultValue(AccessPath.DEFAULT_RAW_PARAM) Boolean raw)
throws InvalidQueryException {
logger.info("Requested query (fetch plan {}, limit : {}, Raw : raw):\n{}", fetchPlan, limit, query, raw);
setHierarchicalMode();
checkHierarchicalMode();
checkIncludeInstancesContexts();
//setRESTCalledMethodLocal(HTTPMETHOD.GET, AccessPath.QUERY_PATH_PART);
CalledMethodProvider.instance.set("rawQuery");
@ -349,7 +352,8 @@ public class Access extends BaseRest {
logger.info("Requested {} instances having a(n) {} ({}={}} with {} ({}={})", resourcetype, relationType,
AccessPath.DIRECTION_PARAM, direction, referenceType, AccessPath.POLYMORPHIC_PARAM, polymorphic);
setHierarchicalMode();
checkHierarchicalMode();
checkIncludeInstancesContexts();
/*
List<String> pathValues = new ArrayList<>();

View File

@ -22,7 +22,7 @@ public class BaseRest {
return true;
}
protected void setHierarchicalMode() {
protected void checkHierarchicalMode() {
try {
List<String> hierarchicalQueryParameterList = uriInfo.getQueryParameters().get(InstancePath.HIERARCHICAL_MODE_PARAM);
if(hierarchicalQueryParameterList!=null && hierarchicalQueryParameterList.size()>0) {
@ -39,4 +39,26 @@ public class BaseRest {
}
}
protected boolean isRequesterAllowedToRequestInstancesContexts() {
// TODO check is the user has the role to query in get instance Contexts
return true;
}
protected void checkIncludeInstancesContexts() {
try {
List<String> includeContextsQueryParameterList = uriInfo.getQueryParameters().get(InstancePath.INCLUDE_CONTEXTS_IN_HEADER_PARAM);
if(includeContextsQueryParameterList!=null && includeContextsQueryParameterList.size()>0) {
String includeContextsBooleanString = includeContextsQueryParameterList.get(0);
boolean includeContexts = Boolean.valueOf(includeContextsBooleanString);
boolean i = includeContexts && isRequesterAllowedToRequestInstancesContexts();
if(i) {
logger.info("The request was performed in hierarchical mode and the requester is allowed. Going to set hierarchical mode.");
ContextUtility.getHierarchicalMode().set(i);
}
}
}catch (Throwable t) {
logger.warn("Unable to properly set the Hierarchical Mode is set", t.getMessage());
}
}
}

View File

@ -67,7 +67,8 @@ public class InstancesManager extends BaseRest {
@QueryParam(InstancePath.POLYMORPHIC_PARAM) @DefaultValue("true") Boolean polymorphic)
throws NotFoundException, ResourceRegistryException {
logger.info("Requested all {}instances of {}", polymorphic ? InstancePath.POLYMORPHIC_PARAM + " " : "", type);
setHierarchicalMode();
checkHierarchicalMode();
checkIncludeInstancesContexts();
/*
Map<String,String> map = new HashMap<String,String>();
map.put(InstancePath.POLYMORPHIC_PARAM, polymorphic.toString());
@ -93,7 +94,8 @@ public class InstancesManager extends BaseRest {
@PathParam(AccessPath.UUID_PATH_PARAM) String uuid) throws NotFoundException, ResourceRegistryException {
logger.info("Requested to check if {} with id {} exists", type, uuid);
//setRESTCalledMethod(HTTPMETHOD.HEAD, type, true);
setHierarchicalMode();
checkHierarchicalMode();
checkIncludeInstancesContexts();
CalledMethodProvider.instance.set("existInstance");
@SuppressWarnings("rawtypes")
@ -130,7 +132,8 @@ public class InstancesManager extends BaseRest {
public String read(@PathParam(AccessPath.TYPE_PATH_PARAM) String type,
@PathParam(AccessPath.UUID_PATH_PARAM) String uuid) throws NotFoundException, ResourceRegistryException {
logger.info("Requested to read {} with id {}", type, uuid);
setHierarchicalMode();
checkHierarchicalMode();
checkIncludeInstancesContexts();
// setRESTCalledMethod(HTTPMETHOD.GET, type, true);
CalledMethodProvider.instance.set("readInstance");

View File

@ -1,6 +1,7 @@
package org.gcube.informationsystem.resourceregistry.utils;
import java.security.Key;
import java.util.Map;
import org.gcube.informationsystem.model.impl.properties.EncryptedImpl;
import org.gcube.informationsystem.model.reference.properties.Encrypted;
@ -71,4 +72,28 @@ public class EncryptedOrient extends ODocument implements org.gcube.informations
}
}
@Override
public Map<String, Object> getAdditionalProperties() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setAdditionalProperties(Map<String, Object> additionalProperties) {
// TODO Auto-generated method stub
}
@Override
public Object getAdditionalProperty(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public void setAdditionalProperty(String key, Object value) {
// TODO Auto-generated method stub
}
}

View File

@ -1,6 +1,7 @@
package org.gcube.informationsystem.resourceregistry.utils;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
import org.gcube.informationsystem.model.reference.properties.Header;
@ -65,5 +66,29 @@ public class HeaderOrient extends ODocument implements Header {
public void setLastUpdateTime(Date lastUpdateTime) {
this.field(Header.LAST_UPDATE_TIME_PROPERTY, lastUpdateTime);
}
@Override
public Map<String, Object> getAdditionalProperties() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setAdditionalProperties(Map<String, Object> additionalProperties) {
// TODO Auto-generated method stub
}
@Override
public Object getAdditionalProperty(String key) {
// TODO Auto-generated method stub
return null;
}
@Override
public void setAdditionalProperty(String key, Object value) {
// TODO Auto-generated method stub
}
}

View File

@ -1,5 +1,7 @@
package org.gcube.informationsystem.resourceregistry.utils;
import java.util.Map;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint;
import com.orientechnologies.orient.core.record.impl.ODocument;
@ -36,5 +38,25 @@ public class PropagationConstraintOrient extends ODocument implements org.gcube.
public void setAddConstraint(AddConstraint addConstraint) {
this.field(PropagationConstraint.ADD_PROPERTY, addConstraint.name());
}
@Override
public Map<String, Object> getAdditionalProperties() {
return null;
}
@Override
public void setAdditionalProperties(Map<String, Object> additionalProperties) {
}
@Override
public Object getAdditionalProperty(String key) {
return null;
}
@Override
public void setAdditionalProperty(String key, Object value) {
}
}

View File

@ -441,6 +441,7 @@ public class ContextManagementTest extends ContextTest {
@Test
public void testGetAll() throws Exception {
List<Context> contexts = getAll();
contexts = ContextCache.getInstance().getContexts();
for(Context context : contexts) {
logger.trace(ElementMapper.marshal(context));
List<IsParentOf> children = context.getChildren();

View File

@ -7,6 +7,7 @@ import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.Calendar;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.UUID;
@ -15,12 +16,14 @@ import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
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.Header;
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;
import org.gcube.informationsystem.resourceregistry.ContextTest;
import org.gcube.informationsystem.resourceregistry.api.contexts.ContextCache;
import org.gcube.informationsystem.resourceregistry.api.contexts.ContextCacheRenewal;
import org.gcube.informationsystem.resourceregistry.api.exceptions.AvailableInAnotherContextException;
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.facet.FacetAvailableInAnotherContextException;
@ -626,5 +629,164 @@ public class BasicTest extends ContextTest {
boolean deleted = hostingNodeManagement.delete();
Assert.assertTrue(deleted);
}
@Test
public void testGetContextsInInstances() throws ResourceRegistryException, Exception {
ContextTest.setContextByName(DEFAULT_TEST_SCOPE);
/* Creating HostingNode */
ContextCache contextCache = ContextCache.getInstance();
contextCache.setContextCacheRenewal(contextCacheRenewal);
ResourceManagement hostingNodeManagement = new ResourceManagement();
hostingNodeManagement.setElementType(HostingNode.NAME);
hostingNodeManagement.setJson(SmartgearResourcesTest.HOSTING_NODE);
String hnJson = hostingNodeManagement.create();
logger.debug("Created : {}", hnJson);
HostingNode hostingNode = ElementMapper.unmarshal(HostingNode.class, hnJson);
logger.debug("Unmarshalled {} {}", HostingNode.NAME, hostingNode);
/* Creating EService */
ResourceManagement eServiceManagement = new ResourceManagement();
eServiceManagement.setElementType(EService.NAME);
eServiceManagement.setJson(SmartgearResourcesTest.ESERVICE);
String eservicejson = eServiceManagement.create();
logger.debug("Created : {}", eservicejson);
EService eService = ElementMapper.unmarshal(EService.class, eservicejson);
logger.debug("Unmarshalled {} {}", EService.NAME, eService);
/* Creating Activates Relation */
PropagationConstraint propagationConstraint = new PropagationConstraintImpl();
propagationConstraint
.setRemoveConstraint(RemoveConstraint.cascade);
propagationConstraint
.setAddConstraint(AddConstraint.unpropagate);
Activates<HostingNode, EService> activates = new ActivatesImpl<>(hostingNode, eService,
propagationConstraint);
IsRelatedToManagement activatesManagement = new IsRelatedToManagement();
activatesManagement.setElementType(Activates.NAME);
String activatesJson = ElementMapper.marshal(activates);
activatesManagement.setJson(activatesJson);
String createdActivatesJson = activatesManagement.create();
logger.debug("Created : {}", createdActivatesJson);
@SuppressWarnings("unchecked")
Activates<HostingNode, EService> createdActivates = ElementMapper.unmarshal(Activates.class, createdActivatesJson);
logger.debug("UnMarshalled {}", createdActivates);
/* ------------------------------------------------------------------ */
logger.debug("Switching to alternative scope");
ContextTest.setContextByName(ALTERNATIVE_TEST_SCOPE);
hostingNodeManagement = new ResourceManagement();
hostingNodeManagement.setUUID(hostingNode.getHeader().getUUID());
hostingNodeManagement.setElementType(Utility.getTypeName(hostingNode.getClass()));
hostingNodeManagement.addToContext(ContextUtility.getCurrentSecurityContext().getUUID());
ContextUtility.getIncludeInstanceContexts().set(true);
String hostingNodeJson = hostingNodeManagement.read();
HostingNode hostingNodeRead = ElementMapper.unmarshal(HostingNode.class, hostingNodeJson);
logger.debug("Unmarshalled {} {}", HostingNode.NAME, hostingNodeRead);
@SuppressWarnings("unchecked")
Collection<String> contextsCollection = (Collection<String>) hostingNodeRead.getHeader().getAdditionalProperty(Header.__CONTEXTS);
Assert.assertTrue(contextsCollection.size()==2);
Set<UUID> hostingNodeContextsUUID = org.gcube.informationsystem.resourceregistry.api.contexts.ContextUtility.getContextUUIDSet(contextsCollection);
Assert.assertTrue(hostingNodeContextsUUID.size()==2);
Set<String> hostingNodeContextFullNames = org.gcube.informationsystem.resourceregistry.api.contexts.ContextUtility.getContextFullNameSet(hostingNodeContextsUUID);
Assert.assertTrue(hostingNodeContextFullNames.size()==2);
logger.debug("Contexts of {} with UUID {} are {}", HostingNode.NAME, hostingNodeManagement.getUUID(), hostingNodeContextFullNames);
for(Facet facet : hostingNode.getFacets()) {
FacetManagement facetManagement = new FacetManagement();
facetManagement.setUUID(facet.getHeader().getUUID());
String typeName = Utility.getTypeName(facet.getClass());
facetManagement.setElementType(typeName);
String facetJson = facetManagement.read();
Facet facetRead = ElementMapper.unmarshal(Facet.class, facetJson);
logger.debug("Unmarshalled {} {}", Utility.getTypeName(facetRead.getClass()), facetRead);
@SuppressWarnings("unchecked")
Collection<String> facetContextsCollection = (Collection<String>) facetRead.getHeader().getAdditionalProperty(Header.__CONTEXTS);
Assert.assertTrue(contextsCollection.size()==2);
Set<UUID> facetContextsUUID = org.gcube.informationsystem.resourceregistry.api.contexts.ContextUtility.getContextUUIDSet(facetContextsCollection);
Assert.assertTrue(hostingNodeContextsUUID.size()==2);
Assert.assertTrue(facetContextsUUID.containsAll(hostingNodeContextsUUID));
Assert.assertTrue(hostingNodeContextsUUID.containsAll(facetContextsUUID));
Set<String> facetContextFullNames = org.gcube.informationsystem.resourceregistry.api.contexts.ContextUtility.getContextFullNameSet(facetContextsUUID);
Assert.assertTrue(facetContextFullNames.size()==2);
logger.debug("Contexts of {} with UUID {} are {}", typeName, facetManagement.getUUID(), facetContextFullNames);
}
activatesManagement = new IsRelatedToManagement();
activatesManagement.setUUID(createdActivates.getHeader().getUUID());
activatesManagement.setElementType(Utility.getTypeName(createdActivates.getClass()));
try {
activatesManagement.read();
String error = String.format("It should not be possible to read %s in %s. A %s should be raised instead", Activates.NAME, ALTERNATIVE_TEST_SCOPE, AvailableInAnotherContextException.class.getSimpleName());
throw new Exception(error);
}catch (AvailableInAnotherContextException e) {
// This is what we expect
}
// Restoring DEFAULT TEST SCOPE otherwise is not possible to read activates relation
// which is not available in ALTERNATIVE_TEST_SCOPE
ContextTest.setContextByName(DEFAULT_TEST_SCOPE);
activatesManagement = new IsRelatedToManagement();
activatesManagement.setUUID(createdActivates.getHeader().getUUID());
activatesManagement.setElementType(Utility.getTypeName(createdActivates.getClass()));
// reading again
String activatesReadJson = activatesManagement.read();
@SuppressWarnings("unchecked")
Activates<HostingNode, EService> activatesRead = ElementMapper.unmarshal(Activates.class, activatesReadJson);
logger.debug("Unmarshalled {} {}", Utility.getTypeName(activatesRead.getClass()), activatesRead);
@SuppressWarnings("unchecked")
Collection<String> activatesContextsCollection = (Collection<String>) activatesRead.getHeader().getAdditionalProperty(Header.__CONTEXTS);
logger.debug("Contexts of {} with UUID {} have the following UUID {}", Activates.NAME, activatesManagement.getUUID(), activatesContextsCollection);
Set<UUID> activatesContextsUUID = org.gcube.informationsystem.resourceregistry.api.contexts.ContextUtility.getContextUUIDSet(activatesContextsCollection);
Assert.assertTrue(activatesContextsUUID.size()==1);
Assert.assertFalse(activatesContextsUUID.containsAll(hostingNodeContextsUUID));
Assert.assertTrue(hostingNodeContextsUUID.containsAll(activatesContextsUUID));
Set<String> activatesContextFullNames = org.gcube.informationsystem.resourceregistry.api.contexts.ContextUtility.getContextFullNameSet(activatesContextsUUID);
Assert.assertTrue(activatesContextFullNames.size()==1);
logger.debug("Contexts of {} with UUID {} are {}", Activates.NAME, activatesManagement.getUUID(), activatesContextFullNames);
eServiceManagement = new ResourceManagement();
eServiceManagement.setUUID(eService.getHeader().getUUID());
eServiceManagement.setElementType(Utility.getTypeName(eService.getClass()));
String eServiceReadJson = eServiceManagement.read();
EService eServiceRead = ElementMapper.unmarshal(EService.class, eServiceReadJson);
logger.debug("Unmarshalled {} {}", Utility.getTypeName(eServiceRead.getClass()), eServiceRead);
@SuppressWarnings("unchecked")
Collection<String> eServiceContextsCollection = (Collection<String>) eServiceRead.getHeader().getAdditionalProperty(Header.__CONTEXTS);
logger.debug("Contexts of {} with UUID {} have the following UUID {}", EService.NAME, eServiceManagement.getUUID(), eServiceContextsCollection);
Set<UUID> eServiceContextsUUID = org.gcube.informationsystem.resourceregistry.api.contexts.ContextUtility.getContextUUIDSet(eServiceContextsCollection);
Assert.assertTrue(eServiceContextsUUID.size()==1);
Assert.assertFalse(eServiceContextsUUID.containsAll(hostingNodeContextsUUID));
Assert.assertTrue(hostingNodeContextsUUID.containsAll(eServiceContextsUUID));
Set<String> eServiceContextFullNames = org.gcube.informationsystem.resourceregistry.api.contexts.ContextUtility.getContextFullNameSet(eServiceContextsUUID);
Assert.assertTrue(eServiceContextFullNames.size()==1);
logger.debug("Contexts of {} with UUID {} are {}", EService.NAME, eServiceManagement.getUUID(), eServiceContextFullNames);
boolean deleted = hostingNodeManagement.delete();
Assert.assertTrue(deleted);
}
}