Loading src/main/java/it/inaf/oats/vospace/DeleteNodeController.java +14 −51 Original line number Diff line number Diff line Loading @@ -20,8 +20,10 @@ import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import net.ivoa.xml.vospace.v2.Node; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; Loading @@ -32,10 +34,9 @@ public class DeleteNodeController extends BaseNodeController { @Autowired private NodeDAO nodeDAO; @GetMapping(value = {"/nodes", "/nodes/**"}, consumes = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}, @DeleteMapping(value = {"/nodes", "/nodes/**"}, produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}) public ResponseEntity<Node> deleteNode(HttpServletRequest request, User principal) { public ResponseEntity<String> deleteNode(HttpServletRequest request, User principal) { String path = getPath(); Loading @@ -60,7 +61,7 @@ public class DeleteNodeController extends BaseNodeController { } else { // Manage all precursors in full path for (int i = 1; i < pathComponents.size(); i++) { for (int i = 0; i < pathComponents.size(); i++) { String tmpPath = pathComponents.get(i); Node mynode = nodeDAO.listNode(tmpPath) .orElseThrow(() -> new NodeNotFoundException(tmpPath)); Loading @@ -71,55 +72,17 @@ public class DeleteNodeController extends BaseNodeController { } // DUPLICATED code from CreateNodeController - BEGIN List<String> nodeOwner = NodeProperties.getNodePropertyByURI(toBeDeletedNode, NodeProperties.CREATOR_URI); //= getNodePropertyByURI( // toBeDeletedNode, "ivo://ivoa.net/vospace/core#creator"); if (nodeOwner == null || nodeOwner.isEmpty() || !nodeOwner.get(0).equals(principal.getName())) { // Node owner check has failed: let's check if user can write // due to group privileges List<String> userGroups = principal.getGroups(); // If the user doesn't belong to any groups throw exception if (userGroups == null || userGroups.isEmpty()) { if(!NodeUtils.checkIfWritable(toBeDeletedNode, principal.getName(), principal.getGroups())) { throw new PermissionDeniedException(path); } List<String> groupWritePropValues = NodeProperties.getNodePropertyByURI(toBeDeletedNode, NodeProperties.CREATOR_URI); // If groupwrite property is absent in Parent Node throw exception if (groupWritePropValues == null || groupWritePropValues.isEmpty()) { throw new PermissionDeniedException(path); try { nodeDAO.deleteNode(path); return ResponseEntity.ok("Node deleted"); } catch(Exception ex) { return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST); } List<String> nodeGroups = NodeProperties.parsePropertyStringToList(groupWritePropValues.get(0)); if (nodeGroups.isEmpty() || !nodeGroups.stream() .anyMatch((i) -> userGroups.contains(i))) { throw new PermissionDeniedException(path); } } // DUPLICATED code from CreateNodeController - END return ResponseEntity.ok(toBeDeletedNode); //return toBeDeletedNode; //return ResponseEntity.ok(nodeDAO.deleteNode(path) // .orElseThrow(() -> new InternalFaultException(path))); } } Loading src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java +1 −14 Original line number Diff line number Diff line Loading @@ -23,10 +23,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; /** * * @author bertocco */ @Repository public class NodeDAO { Loading Loading @@ -126,16 +123,6 @@ public class NodeDAO { return Optional.of(node); } public Optional<String> deleteNode(String path) { // To be filled // In case of failure return empty object to trigger HTTP 500 // status code for InternalFault return Optional.of("OK"); } private String getFirstLevelChildrenSelector(String path) { String select = "(SELECT path FROM node WHERE node_id = (SELECT node_id FROM node_vos_path WHERE vos_path = ?))::varchar || '"; Loading src/test/java/it/inaf/oats/vospace/DeleteNodeControllerTest.java +113 −113 Original line number Diff line number Diff line package it.inaf.oats.vospace; import static it.inaf.oats.vospace.CreateNodeControllerTest.getResourceFileContent; import it.inaf.oats.vospace.datamodel.NodeProperties; import it.inaf.oats.vospace.persistence.NodeDAO; import java.util.List; import java.util.Optional; import net.ivoa.xml.vospace.v2.ContainerNode; import net.ivoa.xml.vospace.v2.DataNode; import net.ivoa.xml.vospace.v2.LinkNode; import net.ivoa.xml.vospace.v2.Node; import net.ivoa.xml.vospace.v2.Property; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; Loading @@ -17,6 +21,7 @@ import org.springframework.test.web.servlet.MockMvc; import org.junit.jupiter.api.Test; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; Loading @@ -34,10 +39,6 @@ public class DeleteNodeControllerTest { @MockBean private NodeDAO nodeDao; @SpyBean @Autowired private DeleteNodeController controller; @Autowired private MockMvc mockMvc; Loading @@ -51,157 +52,156 @@ public class DeleteNodeControllerTest { .delete("/nodes") .header("Authorization", "Bearer user2_token")) .andExpect(status().isForbidden()); /* mockMvc.perform(delete("/members/1"). .header("Authorization", "Bearer user2_token")) .andExpect(status().isNotFound()); mockMvc.perform(delete("/") .header("Authorization", "Bearer user2_token")) .andExpect(status().isNotFound()); */ } @Test public void testNodeNotFound() throws Exception { public void testDeleteFirstLevelNode() throws Exception { when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getDataNode())); when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode())); mockMvc.perform(MockMvcRequestBuilders .delete("/nodes/mynode") .header("Authorization", "Bearer user2_token")) .andExpect(status().isOk()); /* mockMvc.perform(delete("/members/1"). .header("Authorization", "Bearer user2_token")) .andExpect(status().isNotFound()); mockMvc.perform(delete("/") .header("Authorization", "Bearer user2_token")) .andExpect(status().isNotFound()); */ } /* @Test public void testDeleteRoot1() throws Exception { mockMvc.perform(put("/nodes/mydata1") .header("Authorization", "Bearer user2_token")) //.content(requestBody) //.contentType(MediaType.APPLICATION_JSON) //.accept(MediaType.APPLICATION_XML)) //.andDo(print()) .andExpect(status().isOk()); } @Test public void testDeleteRoot2() throws Exception { public void testDeleteMoreLevelNode() throws Exception { when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode("/mynode"))); when(nodeDao.listNode(eq("/mynode/middlenode"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode"))); when(nodeDao.listNode(eq("/mynode/middlenode/myfile.txt"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode/myfile.txt"))); mockMvc.perform(put("/nodes/mydata1") mockMvc.perform(MockMvcRequestBuilders .delete("/nodes/mynode/middlenode/myfile.txt") .header("Authorization", "Bearer user2_token")) //.content(requestBody) //.contentType(MediaType.APPLICATION_JSON) //.accept(MediaType.APPLICATION_XML)) //.andDo(print()) .andExpect(status().isOk()); } @Test public void testDeleteExistingNodeInRoot() throws Exception { public void testLeafNodeNotFound() throws Exception { mockMvc.perform(put("/nodes/mydata1") .header("Authorization", "Bearer user2_token")) //.content(requestBody) //.contentType(MediaType.APPLICATION_JSON) //.accept(MediaType.APPLICATION_XML)) //.andDo(print()) .andExpect(status().isOk()); when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode("/mynode"))); mockMvc.perform(MockMvcRequestBuilders .delete("/nodes/mynode/notexisting") .header("Authorization", "Bearer user2_token")) .andExpect(status().isNotFound()); } @Test public void testDeleteExistingNodeLeaf() throws Exception { public void testMiddleLevelNodeNotFound() throws Exception { mockMvc.perform(put("/nodes/mydata1") .header("Authorization", "Bearer user2_token")) //.content(requestBody) //.contentType(MediaType.APPLICATION_JSON) //.accept(MediaType.APPLICATION_XML)) //.andDo(print()) .andExpect(status().isOk()); when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode("/mynode"))); when(nodeDao.listNode(eq("/mynode/middlenode/myfile.txt"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode/myfile.txt"))); mockMvc.perform(MockMvcRequestBuilders .delete("/mynode/middlenode/myfile.txt") .header("Authorization", "Bearer user2_token")) .andExpect(status().isNotFound()); } @Test public void testDeleteExistingDataLinkInRoot() throws Exception { public void testLinkNodeLeafDelete() throws Exception { mockMvc.perform(put("/nodes/mydata1") when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableLinkNode("/mynode"))); mockMvc.perform(MockMvcRequestBuilders .delete("/nodes/mynode") .header("Authorization", "Bearer user2_token")) //.content(requestBody) //.contentType(MediaType.APPLICATION_JSON) //.accept(MediaType.APPLICATION_XML)) //.andDo(print()) .andExpect(status().isOk()); } @Test public void testDeleteExistingDataLinkLeaf() throws Exception { public void testMiddleLevelLinkNodeDelete() throws Exception { mockMvc.perform(put("/nodes/mydata1") .header("Authorization", "Bearer user2_token")) //.content(requestBody) //.contentType(MediaType.APPLICATION_JSON) //.accept(MediaType.APPLICATION_XML)) //.andDo(print()) .andExpect(status().isOk()); when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode("/mynode"))); when(nodeDao.listNode(eq("/mynode/middlenode"))).thenReturn(Optional.of(getWritableLinkNode("/mynode/middlenode"))); when(nodeDao.listNode(eq("/mynode/middlenode/myfile.txt"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode/myfile.txt"))); mockMvc.perform(MockMvcRequestBuilders .delete("/nodes/mynode/middlenode/myfile.txt") .header("Authorization", "Bearer user2_token")) .andExpect(status().isBadRequest()); } @Test public void testDeleteExistingNodeWithDataLinkInPath() throws Exception { public void testDeleteMoreLevelNodeNotAllowed() throws Exception { mockMvc.perform(put("/nodes/mydata1") .header("Authorization", "Bearer user2_token")) //.content(requestBody) //.contentType(MediaType.APPLICATION_JSON) //.accept(MediaType.APPLICATION_XML)) //.andDo(print()) .andExpect(status().isOk()); when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode("/mynode"))); when(nodeDao.listNode(eq("/mynode/middlenode"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode"))); when(nodeDao.listNode(eq("/mynode/middlenode/myfile.txt"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode/myfile.txt"))); mockMvc.perform(MockMvcRequestBuilders .delete("/nodes/mynode/middlenode/myfile.txt")) .andExpect(status().isForbidden()); } */ private Optional<Node> getRootNode() { ContainerNode root = new ContainerNode(); root.setUri(URI_PREFIX + "/"); root.getNodes().add(getDataNode()); root.getNodes().add(getWritableDataNode()); return Optional.of(root); } private Node getDataNode() { private Node getWritableDataNode() { DataNode node = new DataNode(); List nodeProperties = node.getProperties(); Property groupWriteProp = new Property(); groupWriteProp.setUri(NodeProperties.GROUP_WRITE_URI); groupWriteProp.setValue("group1"); nodeProperties.add(groupWriteProp); node.setUri(URI_PREFIX + "/mynode"); return node; } private Node getWritableDataNode(String path) { DataNode node = new DataNode(); List nodeProperties = node.getProperties(); Property groupWriteProp = new Property(); groupWriteProp.setUri(NodeProperties.GROUP_WRITE_URI); groupWriteProp.setValue("group1"); nodeProperties.add(groupWriteProp); node.setUri(URI_PREFIX + path); return node; } private LinkNode getWritableLinkNode(String path) { LinkNode myNode = new LinkNode(); // Set parent node address at / myNode.setUri("vos://example.com!vospace" + path); // Set groupwrite property Property groups = new Property(); groups.setUri("ivo://ivoa.net/vospace/core#groupwrite"); groups.setValue("group1"); myNode.setProperties(List.of(groups)); return myNode; } } Loading
src/main/java/it/inaf/oats/vospace/DeleteNodeController.java +14 −51 Original line number Diff line number Diff line Loading @@ -20,8 +20,10 @@ import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import net.ivoa.xml.vospace.v2.Node; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; Loading @@ -32,10 +34,9 @@ public class DeleteNodeController extends BaseNodeController { @Autowired private NodeDAO nodeDAO; @GetMapping(value = {"/nodes", "/nodes/**"}, consumes = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}, @DeleteMapping(value = {"/nodes", "/nodes/**"}, produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}) public ResponseEntity<Node> deleteNode(HttpServletRequest request, User principal) { public ResponseEntity<String> deleteNode(HttpServletRequest request, User principal) { String path = getPath(); Loading @@ -60,7 +61,7 @@ public class DeleteNodeController extends BaseNodeController { } else { // Manage all precursors in full path for (int i = 1; i < pathComponents.size(); i++) { for (int i = 0; i < pathComponents.size(); i++) { String tmpPath = pathComponents.get(i); Node mynode = nodeDAO.listNode(tmpPath) .orElseThrow(() -> new NodeNotFoundException(tmpPath)); Loading @@ -71,55 +72,17 @@ public class DeleteNodeController extends BaseNodeController { } // DUPLICATED code from CreateNodeController - BEGIN List<String> nodeOwner = NodeProperties.getNodePropertyByURI(toBeDeletedNode, NodeProperties.CREATOR_URI); //= getNodePropertyByURI( // toBeDeletedNode, "ivo://ivoa.net/vospace/core#creator"); if (nodeOwner == null || nodeOwner.isEmpty() || !nodeOwner.get(0).equals(principal.getName())) { // Node owner check has failed: let's check if user can write // due to group privileges List<String> userGroups = principal.getGroups(); // If the user doesn't belong to any groups throw exception if (userGroups == null || userGroups.isEmpty()) { if(!NodeUtils.checkIfWritable(toBeDeletedNode, principal.getName(), principal.getGroups())) { throw new PermissionDeniedException(path); } List<String> groupWritePropValues = NodeProperties.getNodePropertyByURI(toBeDeletedNode, NodeProperties.CREATOR_URI); // If groupwrite property is absent in Parent Node throw exception if (groupWritePropValues == null || groupWritePropValues.isEmpty()) { throw new PermissionDeniedException(path); try { nodeDAO.deleteNode(path); return ResponseEntity.ok("Node deleted"); } catch(Exception ex) { return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST); } List<String> nodeGroups = NodeProperties.parsePropertyStringToList(groupWritePropValues.get(0)); if (nodeGroups.isEmpty() || !nodeGroups.stream() .anyMatch((i) -> userGroups.contains(i))) { throw new PermissionDeniedException(path); } } // DUPLICATED code from CreateNodeController - END return ResponseEntity.ok(toBeDeletedNode); //return toBeDeletedNode; //return ResponseEntity.ok(nodeDAO.deleteNode(path) // .orElseThrow(() -> new InternalFaultException(path))); } } Loading
src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java +1 −14 Original line number Diff line number Diff line Loading @@ -23,10 +23,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; /** * * @author bertocco */ @Repository public class NodeDAO { Loading Loading @@ -126,16 +123,6 @@ public class NodeDAO { return Optional.of(node); } public Optional<String> deleteNode(String path) { // To be filled // In case of failure return empty object to trigger HTTP 500 // status code for InternalFault return Optional.of("OK"); } private String getFirstLevelChildrenSelector(String path) { String select = "(SELECT path FROM node WHERE node_id = (SELECT node_id FROM node_vos_path WHERE vos_path = ?))::varchar || '"; Loading
src/test/java/it/inaf/oats/vospace/DeleteNodeControllerTest.java +113 −113 Original line number Diff line number Diff line package it.inaf.oats.vospace; import static it.inaf.oats.vospace.CreateNodeControllerTest.getResourceFileContent; import it.inaf.oats.vospace.datamodel.NodeProperties; import it.inaf.oats.vospace.persistence.NodeDAO; import java.util.List; import java.util.Optional; import net.ivoa.xml.vospace.v2.ContainerNode; import net.ivoa.xml.vospace.v2.DataNode; import net.ivoa.xml.vospace.v2.LinkNode; import net.ivoa.xml.vospace.v2.Node; import net.ivoa.xml.vospace.v2.Property; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; Loading @@ -17,6 +21,7 @@ import org.springframework.test.web.servlet.MockMvc; import org.junit.jupiter.api.Test; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; Loading @@ -34,10 +39,6 @@ public class DeleteNodeControllerTest { @MockBean private NodeDAO nodeDao; @SpyBean @Autowired private DeleteNodeController controller; @Autowired private MockMvc mockMvc; Loading @@ -51,157 +52,156 @@ public class DeleteNodeControllerTest { .delete("/nodes") .header("Authorization", "Bearer user2_token")) .andExpect(status().isForbidden()); /* mockMvc.perform(delete("/members/1"). .header("Authorization", "Bearer user2_token")) .andExpect(status().isNotFound()); mockMvc.perform(delete("/") .header("Authorization", "Bearer user2_token")) .andExpect(status().isNotFound()); */ } @Test public void testNodeNotFound() throws Exception { public void testDeleteFirstLevelNode() throws Exception { when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getDataNode())); when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode())); mockMvc.perform(MockMvcRequestBuilders .delete("/nodes/mynode") .header("Authorization", "Bearer user2_token")) .andExpect(status().isOk()); /* mockMvc.perform(delete("/members/1"). .header("Authorization", "Bearer user2_token")) .andExpect(status().isNotFound()); mockMvc.perform(delete("/") .header("Authorization", "Bearer user2_token")) .andExpect(status().isNotFound()); */ } /* @Test public void testDeleteRoot1() throws Exception { mockMvc.perform(put("/nodes/mydata1") .header("Authorization", "Bearer user2_token")) //.content(requestBody) //.contentType(MediaType.APPLICATION_JSON) //.accept(MediaType.APPLICATION_XML)) //.andDo(print()) .andExpect(status().isOk()); } @Test public void testDeleteRoot2() throws Exception { public void testDeleteMoreLevelNode() throws Exception { when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode("/mynode"))); when(nodeDao.listNode(eq("/mynode/middlenode"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode"))); when(nodeDao.listNode(eq("/mynode/middlenode/myfile.txt"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode/myfile.txt"))); mockMvc.perform(put("/nodes/mydata1") mockMvc.perform(MockMvcRequestBuilders .delete("/nodes/mynode/middlenode/myfile.txt") .header("Authorization", "Bearer user2_token")) //.content(requestBody) //.contentType(MediaType.APPLICATION_JSON) //.accept(MediaType.APPLICATION_XML)) //.andDo(print()) .andExpect(status().isOk()); } @Test public void testDeleteExistingNodeInRoot() throws Exception { public void testLeafNodeNotFound() throws Exception { mockMvc.perform(put("/nodes/mydata1") .header("Authorization", "Bearer user2_token")) //.content(requestBody) //.contentType(MediaType.APPLICATION_JSON) //.accept(MediaType.APPLICATION_XML)) //.andDo(print()) .andExpect(status().isOk()); when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode("/mynode"))); mockMvc.perform(MockMvcRequestBuilders .delete("/nodes/mynode/notexisting") .header("Authorization", "Bearer user2_token")) .andExpect(status().isNotFound()); } @Test public void testDeleteExistingNodeLeaf() throws Exception { public void testMiddleLevelNodeNotFound() throws Exception { mockMvc.perform(put("/nodes/mydata1") .header("Authorization", "Bearer user2_token")) //.content(requestBody) //.contentType(MediaType.APPLICATION_JSON) //.accept(MediaType.APPLICATION_XML)) //.andDo(print()) .andExpect(status().isOk()); when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode("/mynode"))); when(nodeDao.listNode(eq("/mynode/middlenode/myfile.txt"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode/myfile.txt"))); mockMvc.perform(MockMvcRequestBuilders .delete("/mynode/middlenode/myfile.txt") .header("Authorization", "Bearer user2_token")) .andExpect(status().isNotFound()); } @Test public void testDeleteExistingDataLinkInRoot() throws Exception { public void testLinkNodeLeafDelete() throws Exception { mockMvc.perform(put("/nodes/mydata1") when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableLinkNode("/mynode"))); mockMvc.perform(MockMvcRequestBuilders .delete("/nodes/mynode") .header("Authorization", "Bearer user2_token")) //.content(requestBody) //.contentType(MediaType.APPLICATION_JSON) //.accept(MediaType.APPLICATION_XML)) //.andDo(print()) .andExpect(status().isOk()); } @Test public void testDeleteExistingDataLinkLeaf() throws Exception { public void testMiddleLevelLinkNodeDelete() throws Exception { mockMvc.perform(put("/nodes/mydata1") .header("Authorization", "Bearer user2_token")) //.content(requestBody) //.contentType(MediaType.APPLICATION_JSON) //.accept(MediaType.APPLICATION_XML)) //.andDo(print()) .andExpect(status().isOk()); when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode("/mynode"))); when(nodeDao.listNode(eq("/mynode/middlenode"))).thenReturn(Optional.of(getWritableLinkNode("/mynode/middlenode"))); when(nodeDao.listNode(eq("/mynode/middlenode/myfile.txt"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode/myfile.txt"))); mockMvc.perform(MockMvcRequestBuilders .delete("/nodes/mynode/middlenode/myfile.txt") .header("Authorization", "Bearer user2_token")) .andExpect(status().isBadRequest()); } @Test public void testDeleteExistingNodeWithDataLinkInPath() throws Exception { public void testDeleteMoreLevelNodeNotAllowed() throws Exception { mockMvc.perform(put("/nodes/mydata1") .header("Authorization", "Bearer user2_token")) //.content(requestBody) //.contentType(MediaType.APPLICATION_JSON) //.accept(MediaType.APPLICATION_XML)) //.andDo(print()) .andExpect(status().isOk()); when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getWritableDataNode("/mynode"))); when(nodeDao.listNode(eq("/mynode/middlenode"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode"))); when(nodeDao.listNode(eq("/mynode/middlenode/myfile.txt"))).thenReturn(Optional.of(getWritableDataNode("/mynode/middlenode/myfile.txt"))); mockMvc.perform(MockMvcRequestBuilders .delete("/nodes/mynode/middlenode/myfile.txt")) .andExpect(status().isForbidden()); } */ private Optional<Node> getRootNode() { ContainerNode root = new ContainerNode(); root.setUri(URI_PREFIX + "/"); root.getNodes().add(getDataNode()); root.getNodes().add(getWritableDataNode()); return Optional.of(root); } private Node getDataNode() { private Node getWritableDataNode() { DataNode node = new DataNode(); List nodeProperties = node.getProperties(); Property groupWriteProp = new Property(); groupWriteProp.setUri(NodeProperties.GROUP_WRITE_URI); groupWriteProp.setValue("group1"); nodeProperties.add(groupWriteProp); node.setUri(URI_PREFIX + "/mynode"); return node; } private Node getWritableDataNode(String path) { DataNode node = new DataNode(); List nodeProperties = node.getProperties(); Property groupWriteProp = new Property(); groupWriteProp.setUri(NodeProperties.GROUP_WRITE_URI); groupWriteProp.setValue("group1"); nodeProperties.add(groupWriteProp); node.setUri(URI_PREFIX + path); return node; } private LinkNode getWritableLinkNode(String path) { LinkNode myNode = new LinkNode(); // Set parent node address at / myNode.setUri("vos://example.com!vospace" + path); // Set groupwrite property Property groups = new Property(); groups.setUri("ivo://ivoa.net/vospace/core#groupwrite"); groups.setValue("group1"); myNode.setProperties(List.of(groups)); return myNode; } }