Skip to content
Snippets Groups Projects
Commit 28259137 authored by Sara Bertocco's avatar Sara Bertocco
Browse files
parents 761620eb 65764bfb
No related branches found
No related tags found
No related merge requests found
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 net.ivoa.xml.vospace.v2.Node;
import org.springframework.http.MediaType;
......@@ -13,6 +14,8 @@ import org.springframework.web.bind.annotation.PutMapping;
import it.inaf.oats.vospace.exception.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.ivoa.xml.vospace.v2.Property;
import java.util.List;
@RestController
public class CreateNodeController extends BaseNodeController {
......@@ -68,6 +71,25 @@ public class CreateNodeController extends BaseNodeController {
throw new PermissionDeniedException(path);
}
// Check if node creator property is set. If not set it according to
// token. In case of creator mistmatch between node and token throw
// exception
String creator = NodeProperties.getNodePropertyByURI(
node, NodeProperties.CREATOR_URI);
if(creator == null)
{
Property creatorProperty = new Property();
creatorProperty.setUri(NodeProperties.CREATOR_URI);
creatorProperty.setValue(principal.getName());
node.getProperties().add(creatorProperty);
} else {
if(!creator.equals(principal.getName()))
// maybe a more specific exception would be more appropriate?
throw new PermissionDeniedException(path);
}
nodeDao.createNode(node);
return node;
......
......@@ -13,6 +13,10 @@ import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import it.inaf.ia2.aa.data.User;
import it.inaf.oats.vospace.datamodel.NodeUtils;
import java.util.Optional;
import it.inaf.oats.vospace.exception.PermissionDeniedException;
@RestController
public class ListNodeController extends BaseNodeController {
......@@ -24,10 +28,21 @@ public class ListNodeController extends BaseNodeController {
@GetMapping(value = {"/nodes", "/nodes/**"},
produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_XML_VALUE})
public ResponseEntity<Node> listNode(HttpServletRequest request) {
public ResponseEntity<Node> listNode(HttpServletRequest request, User principal) {
String path = getPath();
LOG.debug("listNode called for path {}", path);
return ResponseEntity.ok(nodeDAO.listNode(path)
.orElseThrow(() -> new NodeNotFoundException(path)));
Optional<Node> optNode = nodeDAO.listNode(path);
if (optNode.isEmpty()) {
throw new NodeNotFoundException(path);
} else {
if (!NodeUtils.checkIfReadable(
optNode.get(), principal.getName(), principal.getGroups())) {
throw new PermissionDeniedException(path);
}
}
return ResponseEntity.ok(optNode.get());
}
}
......@@ -5,6 +5,7 @@ import java.io.InputStream;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import net.ivoa.xml.vospace.v2.Property;
import it.inaf.oats.vospace.datamodel.NodeProperties;
import net.ivoa.xml.vospace.v2.UnstructuredDataNode;
import org.junit.jupiter.api.Test;
import static org.mockito.ArgumentMatchers.argThat;
......@@ -272,6 +273,57 @@ public class CreateNodeControllerTest {
verify(nodeDao, times(1)).createNode(any());
}
@Test
public void testWriteOwnerAbsent() throws Exception {
String requestBody =
getResourceFileContent("create-unstructured-data-node.xml");
when(nodeDao.listNode(eq("/")))
.thenReturn(Optional.of(getContainerParentNodeWithCreator("/")));
// no node creator specified in xml file
mockMvc.perform(put("/nodes/mydata1")
.header("Authorization", "Bearer user2_token")
.content(requestBody)
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML))
.andDo(print())
.andExpect(status().is2xxSuccessful());
// assert creator properties now matches user2
verify(nodeDao, times(1)).createNode(argThat(node->{
UnstructuredDataNode udn = (UnstructuredDataNode) node;
String creator = NodeProperties.getNodePropertyByURI(
udn, NodeProperties.CREATOR_URI);
return (creator != null && creator.equals("user2"));
}
));
}
@Test
public void testWriteOwnerMismatch() throws Exception {
String requestBody =
getResourceFileContent("create-unstructured-data-node-user1.xml");
when(nodeDao.listNode(eq("/")))
.thenReturn(Optional.of(getContainerParentNodeWithCreator("/")));
// no node creator specified in xml file
mockMvc.perform(put("/nodes/mydata1")
.header("Authorization", "Bearer user2_token")
.content(requestBody)
.contentType(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML))
.andDo(print())
.andExpect(status().is4xxClientError());
// assert createNode is not called
verify(nodeDao, times(0)).createNode(any());
}
@Test
public void testSubPath() throws Exception {
......
package it.inaf.oats.vospace;
import static it.inaf.oats.vospace.VOSpaceXmlTestUtil.loadDocument;
import it.inaf.oats.vospace.datamodel.NodeProperties;
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 net.ivoa.xml.vospace.v2.Property;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import static org.mockito.ArgumentMatchers.eq;
......@@ -16,7 +18,10 @@ 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.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
......@@ -25,6 +30,8 @@ import org.w3c.dom.Document;
@SpringBootTest
@AutoConfigureMockMvc
@ContextConfiguration(classes = {TokenFilterConfig.class})
@TestPropertySource(properties = "spring.main.allow-bean-definition-overriding=true")
public class ListNodeControllerTest {
private static final String URI_PREFIX = "vos://example.com!vospace";
......@@ -78,9 +85,38 @@ public class ListNodeControllerTest {
.andExpect(status().isNotFound());
}
@Test
public void testPermissionDeniedUser() throws Exception {
Node node = getDataNodeByOwnership("user2","group1");
when(dao.listNode(eq("/mynode"))).thenReturn(Optional.of(node));
mockMvc.perform(get("/nodes/mynode")
.header("Authorization", "Bearer user1_token")
.accept(MediaType.APPLICATION_XML))
.andExpect(status().is4xxClientError());
}
@Test
public void testGrantedByGroup() throws Exception {
Node node = getDataNodeByOwnership("user1","group1");
when(dao.listNode(eq("/mynode"))).thenReturn(Optional.of(node));
mockMvc.perform(get("/nodes/mynode")
.header("Authorization", "Bearer user2_token")
.accept(MediaType.APPLICATION_XML))
.andExpect(status().is2xxSuccessful());
}
private Optional<Node> getRootNode() {
ContainerNode root = new ContainerNode();
root.setUri(URI_PREFIX + "/");
Property publicProperty = new Property();
publicProperty.setUri(NodeProperties.PUBLIC_READ_URI);
publicProperty.setValue("true");
root.getProperties().add(publicProperty);
root.getNodes().add(getDataNode());
return Optional.of(root);
}
......@@ -88,6 +124,29 @@ public class ListNodeControllerTest {
private Node getDataNode() {
DataNode node = new DataNode();
node.setUri(URI_PREFIX + "/mynode");
Property publicProperty = new Property();
publicProperty.setUri(NodeProperties.PUBLIC_READ_URI);
publicProperty.setValue("true");
node.getProperties().add(publicProperty);
return node;
}
private Node getDataNodeByOwnership(String ownerID, String group)
{
DataNode node = new DataNode();
node.setUri(URI_PREFIX + "/mynode");
// Set owner
Property creatorProperty = new Property();
creatorProperty.setUri(NodeProperties.CREATOR_URI);
creatorProperty.setValue(ownerID);
node.getProperties().add(creatorProperty);
// set group
Property readGroupProperty = new Property();
readGroupProperty.setUri(NodeProperties.GROUP_READ_URI);
readGroupProperty.setValue(group);
node.getProperties().add(readGroupProperty);
return node;
}
}
<vos:node xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:vos="http://www.ivoa.net/xml/VOSpace/v2.0" xsi:type="vos:UnstructuredDataNode" uri="vos://example.com!vospace/mydata1">
<vos:properties>
<vos:property uri="ivo://ivoa.net/vospace/core#description">test value</vos:property>
<vos:property uri="ivo://ivoa.net/vospace/core#creator">user1</vos:property>
</vos:properties>
<vos:accepts/>
<vos:provides/>
<vos:capabilities/>
</vos:node>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment