package org.gcube.informationsystem.resourceregistry.contexts; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.UUID; import org.gcube.com.fasterxml.jackson.core.JsonProcessingException; import org.gcube.informationsystem.base.reference.IdentifiableElement; import org.gcube.informationsystem.contexts.impl.entities.ContextImpl; import org.gcube.informationsystem.contexts.reference.entities.Context; import org.gcube.informationsystem.contexts.reference.relations.IsParentOf; import org.gcube.informationsystem.resourceregistry.ContextTest; import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; import org.gcube.informationsystem.resourceregistry.api.exceptions.contexts.ContextAlreadyPresentException; import org.gcube.informationsystem.resourceregistry.api.exceptions.contexts.ContextException; import org.gcube.informationsystem.resourceregistry.api.exceptions.contexts.ContextNotFoundException; import org.gcube.informationsystem.resourceregistry.contexts.entities.ContextManagement; import org.gcube.informationsystem.resourceregistry.contexts.security.ContextSecurityContext; import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext; import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext.PermissionMode; import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext.SecurityType; import org.gcube.informationsystem.resourceregistry.utils.MetadataUtility; import org.gcube.informationsystem.serialization.ElementMapper; import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.arcadedb.remote.RemoteDatabase; /** * @author Luca Frosini (ISTI - CNR) */ public class ContextManagementTest extends ContextTest { private static Logger logger = LoggerFactory.getLogger(ContextManagementTest.class); public static final String CTX_NAME_A = "A"; public static final String CTX_NAME_B = "B"; public static final String CTX_NAME_C = "C"; public static void checkUUUIDAndMetadata(IdentifiableElement er, UUID uuid, boolean create) { Assert.assertTrue(er.getMetadata() != null); Assert.assertTrue(er.getID() != null); if(uuid != null) { Assert.assertTrue(er.getID().compareTo(uuid) == 0); } String user = MetadataUtility.getUser(); Assert.assertTrue(er.getMetadata().getLastUpdateBy().compareTo(user) == 0); if(create) { Assert.assertTrue(er.getMetadata().getCreatedBy().compareTo(user) == 0); Assert.assertTrue(er.getMetadata().getCreationTime().compareTo(er.getMetadata().getLastUpdateTime()) == 0); } else { Assert.assertTrue(er.getMetadata().getCreationTime().before(er.getMetadata().getLastUpdateTime())); } } protected void assertions(Context pre, Context post, boolean checkParent, boolean create) throws ResourceRegistryException { if(checkParent) { if(pre.getMetadata() != null) { checkUUUIDAndMetadata(post, pre.getID(), create); } else { checkUUUIDAndMetadata(post, null, create); } } Assert.assertTrue(pre.getName().compareTo(post.getName()) == 0); if(checkParent && pre.getParent() != null && post.getParent() != null) { Context preParent = pre.getParent().getSource(); Context postParent = post.getParent().getSource(); assertions(preParent, postParent, false, false); } } protected void roleUserAssertions(UUID uuid, UUID oldParentUUID, boolean deleted) throws ResourceRegistryException { ContextSecurityContext contextSecurityContext = ContextSecurityContext.getInstance(); RemoteDatabase database = contextSecurityContext.getRemoteDatabase(PermissionMode.READER); // OSecurity oSecurity = oDatabaseDocument.getMetadata().getSecurity(); SecurityContext securityContext = null; if(deleted) { securityContext = new SecurityContext(uuid); } else { securityContext = ContextUtility.getInstance().getSecurityContextByUUID(uuid); } boolean[] booleanArray = new boolean[] {false, true}; for(boolean hierarchic : booleanArray) { for(PermissionMode permissionMode : PermissionMode.values()) { String role = securityContext.getSecurityRoleOrUserName(permissionMode, SecurityType.ROLE, hierarchic); Role oRole = oSecurity.getRole(role); Assert.assertEquals(oRole == null, deleted); String user = securityContext.getSecurityRoleOrUserName(permissionMode, SecurityType.USER, hierarchic); User oUser = oSecurity.getUser(user); Assert.assertEquals(oUser == null, deleted); if(oUser != null) { Assert.assertTrue(oUser.hasRole(oRole.getName(), false)); } if(hierarchic) { SecurityContext parent = null; if(deleted) { if(oldParentUUID != null) { parent = ContextUtility.getInstance().getSecurityContextByUUID(oldParentUUID); } } parent = securityContext.getParentSecurityContext(); while(parent != null) { String parentUser = parent.getSecurityRoleOrUserName(permissionMode, SecurityType.USER, hierarchic); User parentOUser = oSecurity.getUser(parentUser); Assert.assertTrue(parentOUser != null); Assert.assertEquals(parentOUser.hasRole(oRole.getName(), false), !deleted); parent = parent.getParentSecurityContext(); } } } } } protected Context read(UUID uuid) throws ResourceRegistryException, IOException { ContextManagement contextManagement = new ContextManagement(); contextManagement.setUUID(uuid); String contextString = contextManagement.read().toString(); logger.debug("Read {}", contextString); roleUserAssertions(uuid, null, false); return ElementMapper.unmarshal(Context.class, contextString); } protected Context create(Context context) throws ResourceRegistryException, IOException { ContextManagement contextManagement = new ContextManagement(); contextManagement.setJson(ElementMapper.marshal(context)); String contextString = contextManagement.create(); logger.debug("Created {}", contextString); Context c = ElementMapper.unmarshal(Context.class, contextString); assertions(context, c, true, true); roleUserAssertions(c.getID(), null, false); return c; } protected Context update(Context context) throws ResourceRegistryException, IOException { ContextManagement contextManagement = new ContextManagement(); contextManagement.setJson(ElementMapper.marshal(context)); String contextString = contextManagement.update(); logger.debug("Updated {}", contextString); Context c = ElementMapper.unmarshal(Context.class, contextString); assertions(context, c, true, false); roleUserAssertions(c.getID(), null, false); return c; } protected void delete(UUID uuid) throws ResourceRegistryException { ContextManagement contextManagement = new ContextManagement(); contextManagement.setUUID(uuid); SecurityContext securityContext = ContextUtility.getInstance().getSecurityContextByUUID(uuid); UUID oldParentUUID = null; if(securityContext.getParentSecurityContext() != null) { oldParentUUID = securityContext.getParentSecurityContext().getUUID(); } contextManagement.delete(); roleUserAssertions(uuid, oldParentUUID, true); logger.debug("Deleted {} with UUID {}", Context.NAME, uuid); } protected void delete(Context context) throws ResourceRegistryException { delete(context.getID()); } protected void invalidCreate(Context context) throws ResourceRegistryException, IOException { try { Context c = create(context); throw new RuntimeException(ElementMapper.marshal(c) + " was created successfully. This is not what we expected"); } catch(ContextAlreadyPresentException e) { logger.debug("As expected {} cannot be created.", ElementMapper.marshal(context)); } } protected void invalidUpdate(Context context) throws ResourceRegistryException, IOException { try { Context c = update(context); throw new RuntimeException(ElementMapper.marshal(c) + " was updated successfully. This is not what we expected"); } catch(ContextAlreadyPresentException e) { logger.debug("As expected {} cannot be updated.", ElementMapper.marshal(context)); } } protected void invalidDelete(Context context) throws ResourceRegistryException, JsonProcessingException { String contextString = ElementMapper.marshal(context); try { delete(context); throw new RuntimeException(contextString + " was deleted successfully. This is not what we expected"); } catch(ContextException e) { logger.debug("As expected {} cannot be deleted.", contextString); } } /* @Test public void createDelete() throws Exception { Context contextA1 = new ContextImpl(CTX_NAME_A); contextA1 = create(contextA1); delete(contextA1); logger.debug("The DB should be now clean"); } */ @Test public void completeTest() throws Exception { Context contextA1 = new ContextImpl(CTX_NAME_A); contextA1 = create(contextA1); // ________A1________ Context contextA2 = new ContextImpl(CTX_NAME_A); contextA2.setParent(contextA1); contextA2 = create(contextA2); // ________A1________ // ___A2 Context contextB3 = new ContextImpl(CTX_NAME_B); contextB3.setParent(contextA2); contextB3 = create(contextB3); // ________A1________ // ___A2 // B3 Context contextB4 = new ContextImpl(CTX_NAME_B); contextB4.setParent(contextA1); contextB4 = create(contextB4); // ________A1________ // ___A2_______B4____ // B3 Context contextA5 = new ContextImpl(CTX_NAME_A); contextA5.setParent(contextB4); contextA5 = create(contextA5); // ________A1________ // ___A2_______B4____ // B3______________A5 invalidCreate(contextA1); // Trying to recreate A1. Fails invalidCreate(contextA2); // Trying to recreate A2. Fails invalidCreate(contextB3); // Trying to recreate B3. Fails invalidCreate(contextB4); // Trying to recreate B4. Fails invalidCreate(contextA5); // Trying to recreate A5. Fails Context nullContext = null; // Trying to move A5 as root. It fails due to A1. contextA5.setParent(nullContext); invalidUpdate(contextA5); contextA5.setParent(contextB4); // ________A1________ // ___A2_______B4____ // B3______________A5 nullContext = null; contextB4.setParent(nullContext); update(contextB4); // _____A1____B4_____ // __A2__________A5__ // B3 contextB4.setParent(contextA1); update(contextB4); // ________A1________ // ___A2_______B4____ // B3______________A5 // Trying to rename with the new name A. It fails due to A5. contextB3.setName(CTX_NAME_A); update(contextB3); // ________A1________ // ___A2_______B4____ // A3______________A5 // After Restoring name B, trying to move B3 as child of A1. It fails due to B4. contextB3.setName(CTX_NAME_B); contextB3.setParent(contextA1); invalidUpdate(contextB3); // ________A1________ // ___A2_______B4____ // A3______________A5 // Restoring A3 (was B3) as B3 and with parent A2.OK. contextB3.setName(CTX_NAME_B); contextB3.setParent(contextA2); update(contextB3); // ________A1________ // ___A2_______B4____ // B3______________A5 // This update should not has eny effects except updating the lastUpdateTime. contextB3.setName(CTX_NAME_B); contextB3.setParent(contextA2); update(contextB3); // Trying to move A5 as child of A1. It fails due to A2. contextA5.setParent(contextA1); invalidUpdate(contextA5); // Restoring A5 contextA5.setParent(contextB4); // ________A1________ // ___A2_______B4____ // B3______________A5 // Moving B3 as child of B4. OK. contextB3.setParent(contextB4); update(contextB3); // ________A1________ // ___A2_______B4____ // ________B3______A5 // Restoring the initial situation by moving B3 as child of A2. OK. contextB3.setParent(contextA2); update(contextB3); // ________A1________ // ___A2_______B4____ // B3______________A5 // Renaming B3 as C3. OK. contextB3.setName(CTX_NAME_C); update(contextB3); // ________A1________ // ___A2_______B4____ // C3______________A5 // Moving C3 (was B3) as child of A1. Now it is possible. OK. contextB3.setParent(contextA1); update(contextB3); // ________A1________ // ___A2___C3___B4___ // ________________A5 // Trying to rename C3 (was B3) newly to B3. Fails due to B4. contextB3.setName(CTX_NAME_B); invalidUpdate(contextB3); // ________A1________ // ___A2___C3___B4___ // ________________A5 // Moving back C3 (was B3) as child of A2. OK. contextB3.setParent(contextA2); update(contextB3); // ________A1________ // ___A2_______B4____ // C3______________A5 // Renaming C3 (was B3) to B3. OK. contextB3.setName(CTX_NAME_B); update(contextB3); // ________A1________ // ___A2_______B4____ // B3______________A5 /* // This updates (move) has been made to test HRoles and HUsers contextA2.setParent(contextA5); update(contextA2); // __A1______________ // _____B4___________ // ________A5________ // ___________A2_____ // ______________B3__ contextA5.setParent(contextA1); update(contextA5); // _________A1________ // ______A5_____B4____ // ___A2______________ // B3_________________ contextA5.setParent(contextB4); update(contextA5); // __A1______________ // _____B4___________ // ________A5________ // ___________A2_____ // ______________B3__ contextA2.setParent(contextA1); update(contextA2); // ________A1________ // ___A2_______B4____ // B3______________A5 */ // The following delete are not allowed because they are not child contexts invalidDelete(contextA1); invalidDelete(contextA2); invalidDelete(contextB4); delete(contextA5); // ________A1________ // ___A2_______B4____ // B3 try { delete(contextA5); } catch(ContextNotFoundException e) { logger.debug("The context with uuid {} was not found. (Was already deleted)", contextA5.getID()); } delete(contextB3); // ________A1________ // ___A2_______B4____ delete(contextB4); // ________A1________ // ___A2 delete(contextA2); // ________A1________ Context contextC = new ContextImpl(CTX_NAME_C); contextC.setID(contextA1.getID()); invalidCreate(contextC); delete(contextA1); logger.debug("The DB should be now clean"); } private List getAll() throws Exception { ContextManagement contextManagement = new ContextManagement(); String allString = contextManagement.all(false); logger.trace(allString); List all = ElementMapper.unmarshalList(Context.class, allString); return all; } /* // @Test public void deleteAll() throws Exception { ContextTest.setContextByName(PARENT_DEFAULT_TEST_SCOPE); List all = getAll(); while(all.size()>0) { for (Context context : all) { logger.trace(ElementMapper.marshal(context)); List children = context.getChildren(); if(children==null || children.size()==0) { // delete(context); } } all = getAll(); } } */ @Test public void testGetAll() throws Exception { List contexts = getAll(); contexts = ServerContextCache.getInstance().getContexts(); for(Context context : contexts) { logger.info(ElementMapper.marshal(context)); List children = context.getChildren(); for(IsParentOf child : children) { Assert.assertTrue(child.getSource() == context); Context childContext = child.getTarget(); Assert.assertTrue(childContext.getParent().getSource() == context); } roleUserAssertions(context.getID(), null, false); } } // @Test public void readContext() throws ResourceRegistryException, IOException { Context context = read(UUID.fromString("")); logger.debug("{}", context); } // @Test public void deleteContext() throws ResourceRegistryException, IOException { Context context = read(UUID.fromString("")); delete(context); } @Test public void testContextCache() throws Exception { List contexts = getAll(); logger.debug("{}", contexts); ServerContextCache contextCache = ServerContextCache.getInstance(); Map uuidToContextFullName = contextCache.getUUIDToContextFullNameAssociation(); logger.debug("{}", uuidToContextFullName); List contextsFromCache = contextCache.getContexts(); for(Context c : contextsFromCache) { UUID uuid = c.getID(); if(c.getParent()!=null) { IsParentOf isParentOf = c.getParent(); Context parentContext = isParentOf.getSource(); UUID parentUUID = parentContext.getID(); Assert.assertTrue(parentContext.getName().compareTo(contextCache.getContextByUUID(parentUUID).getName())==0); List children = parentContext.getChildren(); boolean found = false; for(IsParentOf ipo : children) { if(ipo.equals(isParentOf)) { found = true; break; } } Assert.assertTrue(found); logger.debug("{} : {} (parent {} : {})", c.getID(), contextCache.getContextFullNameByUUID(uuid), parentUUID, contextCache.getContextFullNameByUUID(parentUUID)); }else { logger.debug("{} : {}", c.getID(), contextCache.getContextFullNameByUUID(uuid)); } } Context currentContext = read(ContextUtility.getCurrentSecurityContext().getUUID()); logger.debug("Current context : {}", currentContext); for(Context c : contexts) { UUID uuid = c.getID(); Context context = read(uuid); String fullName = ServerContextCache.getInstance().getContextFullNameByUUID(uuid); logger.debug("{} - {} : {}", uuid, fullName, context); } } }