Commit 773e1e0d authored by Nicola Fulvio Calabria's avatar Nicola Fulvio Calabria
Browse files

#3636 - Handle permissions in ListNodeController

parent 830955aa
Loading
Loading
Loading
Loading
+19 −4
Original line number Diff line number Diff line
@@ -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());
    }
}
+59 −0
Original line number Diff line number Diff line
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;       
    }
}