Commit 4914df4b authored by Nicola Fulvio Calabria's avatar Nicola Fulvio Calabria
Browse files

Added LinkNode support to pullFromVoSpace

parent f1bf44a8
Loading
Loading
Loading
Loading
+17 −1
Original line number Original line Diff line number Diff line
@@ -6,15 +6,21 @@
package it.inaf.oats.vospace;
package it.inaf.oats.vospace;


import it.inaf.oats.vospace.datamodel.NodeUtils;
import it.inaf.oats.vospace.datamodel.NodeUtils;
import it.inaf.oats.vospace.exception.InvalidArgumentException;
import it.inaf.oats.vospace.exception.InvalidURIException;
import it.inaf.oats.vospace.exception.InvalidURIException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import net.ivoa.xml.vospace.v2.LinkNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;


public abstract class BaseNodeController {
public abstract class BaseNodeController {


    @Autowired
    @Autowired
    private HttpServletRequest servletRequest;
    private HttpServletRequest servletRequest;
    
    
    @Value("${vospace-authority}")
    protected String authority;     
    
    protected String getPath() {       
    protected String getPath() {       
        String requestURL = servletRequest.getRequestURL().toString();
        String requestURL = servletRequest.getRequestURL().toString();
        try {
        try {
@@ -27,4 +33,14 @@ public abstract class BaseNodeController {
    protected String getParentPath(String path) {
    protected String getParentPath(String path) {
        return NodeUtils.getParentPath(path);
        return NodeUtils.getParentPath(path);
    }
    }
    
    protected void validateInternalLinkNode(LinkNode linkNode) {
        String target = linkNode.getTarget();
        // I validate it here to add context easily
        if (target == null) {
            throw new InvalidArgumentException("LinkNode in payload has no target element specified");
        }

        URIUtils.returnVosPathFromNodeURI(linkNode.getTarget(), authority);
    }
}
}
+2 −14
Original line number Original line Diff line number Diff line
@@ -6,7 +6,6 @@
package it.inaf.oats.vospace;
package it.inaf.oats.vospace;


import it.inaf.ia2.aa.data.User;
import it.inaf.ia2.aa.data.User;
import it.inaf.oats.vospace.exception.InvalidArgumentException;
import it.inaf.oats.vospace.exception.InvalidURIException;
import it.inaf.oats.vospace.exception.InvalidURIException;
import net.ivoa.xml.vospace.v2.LinkNode;
import net.ivoa.xml.vospace.v2.LinkNode;
import net.ivoa.xml.vospace.v2.Node;
import net.ivoa.xml.vospace.v2.Node;
@@ -17,7 +16,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.slf4j.Logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;


@RestController
@RestController
public class CreateNodeController extends BaseNodeController {
public class CreateNodeController extends BaseNodeController {
@@ -27,9 +25,6 @@ public class CreateNodeController extends BaseNodeController {
    @Autowired
    @Autowired
    private CreateNodeService createNodeService;
    private CreateNodeService createNodeService;


    @Value("${vospace-authority}")
    private String authority;

    @PutMapping(value = {"/nodes", "/nodes/**"},
    @PutMapping(value = {"/nodes", "/nodes/**"},
            consumes = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE},
            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})
            produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
@@ -40,7 +35,7 @@ public class CreateNodeController extends BaseNodeController {
        LOG.debug("createNodeController called for node with URI {} and PATH {}", node.getUri(), path);
        LOG.debug("createNodeController called for node with URI {} and PATH {}", node.getUri(), path);


        // Get Node path (and validates it too)
        // Get Node path (and validates it too)
        String decodedURIPathFromNode = URIUtils.returnVosPathFromNodeURI(node.getUri(), authority);
        String decodedURIPathFromNode = URIUtils.returnVosPathFromNodeURI(node.getUri(), this.authority);


        LOG.debug("createNodeController URI: {} decoded as {}", node.getUri(), decodedURIPathFromNode);
        LOG.debug("createNodeController URI: {} decoded as {}", node.getUri(), decodedURIPathFromNode);


@@ -59,14 +54,7 @@ public class CreateNodeController extends BaseNodeController {
    private void validateInputNode(Node node) {
    private void validateInputNode(Node node) {


        if (node instanceof LinkNode) {
        if (node instanceof LinkNode) {
            LinkNode linkNode = (LinkNode) node;
            this.validateInternalLinkNode((LinkNode) node);
            String target = linkNode.getTarget();
            // I validate it here to add context easily
            if (target == null) {
                throw new InvalidArgumentException("LinkNode in payload has no target element specified");
            }

            URIUtils.returnVosPathFromNodeURI(linkNode.getTarget(), authority);
        }
        }


    }
    }
+4 −0
Original line number Original line Diff line number Diff line
@@ -13,6 +13,7 @@ import it.inaf.oats.vospace.persistence.NodeDAO;
import java.util.List;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import net.ivoa.xml.vospace.v2.DataNode;
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.Node;
import net.ivoa.xml.vospace.v2.View;
import net.ivoa.xml.vospace.v2.View;
import org.slf4j.Logger;
import org.slf4j.Logger;
@@ -65,8 +66,11 @@ public class SetNodeController extends BaseNodeController {


        // This method cannot be used to modify the accepts or provides list of Views for the Node.
        // This method cannot be used to modify the accepts or provides list of Views for the Node.
        // Only DataNodes has Views (see VOSpace Data Model)
        // Only DataNodes has Views (see VOSpace Data Model)
        // Also if input node is LinkNode, target must be validated as internal URI
        if (node instanceof DataNode) {
        if (node instanceof DataNode) {
            checkViews((DataNode) node, (DataNode) toBeModifiedNode);
            checkViews((DataNode) node, (DataNode) toBeModifiedNode);
        } else if(node instanceof LinkNode) {
            this.validateInternalLinkNode((LinkNode) node);
        }
        }


        //The service SHOULD throw a HTTP 500 status code including an InternalFault fault 
        //The service SHOULD throw a HTTP 500 status code including an InternalFault fault 
+22 −5
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@ import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import net.ivoa.xml.uws.v1.JobSummary;
import net.ivoa.xml.uws.v1.JobSummary;
import net.ivoa.xml.vospace.v2.DataNode;
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.Node;
import net.ivoa.xml.vospace.v2.Protocol;
import net.ivoa.xml.vospace.v2.Protocol;
import net.ivoa.xml.vospace.v2.Transfer;
import net.ivoa.xml.vospace.v2.Transfer;
@@ -127,7 +128,16 @@ public class UriService {
            User user) {
            User user) {
        Optional<Node> optNode = nodeDao.listNode(relativePath);
        Optional<Node> optNode = nodeDao.listNode(relativePath);
        if (optNode.isPresent()) {
        if (optNode.isPresent()) {
            return optNode.get();
            Node node = optNode.get();
            if (jobType.equals(JobService.JobDirection.pullFromVoSpace)) {
                if (node instanceof LinkNode) {
                    if (!NodeUtils.checkIfReadable(node, user.getName(), user.getGroups())) {
                        throw PermissionDeniedException.forPath(relativePath);
                    }
                    node = this.followLink((LinkNode) node);
                }
            }
            return node;
        } else {
        } else {
            switch (jobType) {
            switch (jobType) {
                case pullFromVoSpace:
                case pullFromVoSpace:
@@ -152,8 +162,8 @@ public class UriService {
        List<String> groups = user.getGroups();
        List<String> groups = user.getGroups();


        // Check privileges write or read according to job type
        // Check privileges write or read according to job type
        JobService.JobDirection jobType = 
        JobService.JobDirection jobType
                JobDirection.getJobDirectionEnumFromTransfer(transfer);
                = JobDirection.getJobDirectionEnumFromTransfer(transfer);
        Node node = this.getEndpointNode(relativePath, jobType, user);
        Node node = this.getEndpointNode(relativePath, jobType, user);


        switch (jobType) {
        switch (jobType) {
@@ -266,4 +276,11 @@ public class UriService {


        return (Transfer) job.getJobInfo().getAny().get(0);
        return (Transfer) job.getJobInfo().getAny().get(0);
    }
    }

    private Node followLink(LinkNode linkNode) {
        String targetPath = URIUtils.returnVosPathFromNodeURI(linkNode.getTarget(), authority);
        Optional<Node> targetNode = nodeDao.listNode(targetPath);
        return targetNode.orElseThrow(() -> new InternalFaultException("Broken Link to target: " + targetPath));

    }
}
}