Skip to content
Snippets Groups Projects
Commit c4531a11 authored by Sara Bertocco's avatar Sara Bertocco
Browse files

Working on redmine task #3549

parent 2d68d297
No related branches found
No related tags found
No related merge requests found
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package it.inaf.oats.vospace;
import it.inaf.ia2.aa.data.User;
import it.inaf.oats.vospace.datamodel.NodeProperties;
import it.inaf.oats.vospace.datamodel.NodeUtils;
import it.inaf.oats.vospace.exception.ContainerNotFoundException;
import it.inaf.oats.vospace.exception.InternalFaultException;
import it.inaf.oats.vospace.exception.LinkFoundException;
import it.inaf.oats.vospace.exception.NodeNotFoundException;
import it.inaf.oats.vospace.exception.PermissionDeniedException;
import it.inaf.oats.vospace.persistence.NodeDAO;
import java.util.ArrayList;
import java.util.List;
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.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
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},
produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<Node> deleteNode(HttpServletRequest request, User principal) {
String path = getPath();
// Check if the node is present,
// if the node does not exist the service SHALL throw a HTTP 404 status code
// including a NodeNotFound fault in the entity-body
// If note present, got it
Node toBeDeletedNode = nodeDAO.listNode(path)
.orElseThrow(() -> new NodeNotFoundException(path));
// If a parent node in the URI path is a LinkNode, the service SHALL throw
// a HTTP 400 status code including a LinkFound fault in the entity-body.
// For example, given the URI path /a/b/c, the service must throw a HTTP 400
// status code including a LinkFound fault in the entity-body if either /a
// or /a/b are LinkNodes.
List<String> pathComponents = NodeUtils.subPathComponents(path);
if (pathComponents.size() == 0) {
// Manage root node
throw new PermissionDeniedException("root");
} else {
// Manage all precursors in full path
for (int i = 1; i < pathComponents.size(); i++) {
String tmpPath = pathComponents.get(i);
Node mynode = nodeDAO.listNode(tmpPath)
.orElseThrow(() -> new NodeNotFoundException(tmpPath));
if (mynode.getType().equals("vos:LinkNode") && i < pathComponents.size()-1) // a LinkNode leaf can be deleted
throw new LinkFoundException(tmpPath);
}
}
// 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()) {
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);
}
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)));
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package it.inaf.oats.vospace.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) // Status code 500
public class InternalFaultException extends VoSpaceException {
public InternalFaultException(String msg) {
super("InternalFaultException: " + msg);
}
}
package it.inaf.oats.vospace;
import static it.inaf.oats.vospace.CreateNodeControllerTest.getResourceFileContent;
import it.inaf.oats.vospace.persistence.NodeDAO;
import java.util.Optional;
import net.ivoa.xml.vospace.v2.ContainerNode;
import net.ivoa.xml.vospace.v2.DataNode;
import net.ivoa.xml.vospace.v2.Node;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
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.MediaType;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@ContextConfiguration(classes = {TokenFilterConfig.class})
@TestPropertySource(properties = "spring.main.allow-bean-definition-overriding=true")
@AutoConfigureMockMvc
public class DeleteNodeControllerTest {
private static final String URI_PREFIX = "vos://example.com!vospace";
@MockBean
private NodeDAO nodeDao;
@SpyBean
@Autowired
private DeleteNodeController controller;
@Autowired
private MockMvc mockMvc;
@Test
public void testDeleteRootNode() throws Exception {
when(nodeDao.listNode(eq("/"))).thenReturn(getRootNode());
mockMvc.perform(MockMvcRequestBuilders
.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 {
when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(getDataNode()));
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 {
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 testDeleteExistingNodeInRoot() 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 testDeleteExistingNodeLeaf() 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 testDeleteExistingDataLinkInRoot() 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 testDeleteExistingDataLinkLeaf() 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 testDeleteExistingNodeWithDataLinkInPath() 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());
}
*/
private Optional<Node> getRootNode() {
ContainerNode root = new ContainerNode();
root.setUri(URI_PREFIX + "/");
root.getNodes().add(getDataNode());
return Optional.of(root);
}
private Node getDataNode() {
DataNode node = new DataNode();
node.setUri(URI_PREFIX + "/mynode");
return node;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment