Skip to content
CreateNodeController.java 5.82 KiB
Newer Older
Sara Bertocco's avatar
Sara Bertocco committed
package it.inaf.oats.vospace;

import it.inaf.oats.vospace.datamodel.NodeProperties;
import it.inaf.oats.vospace.datamodel.NodeUtils;
Sara Bertocco's avatar
Sara Bertocco committed
import net.ivoa.xml.vospace.v2.Node;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Autowired;
import it.inaf.oats.vospace.persistence.NodeDAO;
import org.springframework.beans.factory.annotation.Value;
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;
Sara Bertocco's avatar
Sara Bertocco committed

@RestController
public class CreateNodeController extends BaseNodeController {
Sara Bertocco's avatar
Sara Bertocco committed

    private static final Logger LOG = LoggerFactory.getLogger(CreateNodeController.class);
    @Value("${vospace-authority}")
    private String authority;

            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 Node createNode(@RequestBody Node node, User principal) {

        String path = getPath();
        LOG.debug("createNode called for path {}", path);
Sara Bertocco's avatar
Sara Bertocco committed

            throw new InvalidURIException(node.getUri());
        // Check if payload URI is consistent with http request
        if (!isUrlConsistentWithPayloadURI(node.getUri(), path)) {
            throw new InvalidURIException(node.getUri(), path);
        }

        // Check if another node is already present at specified path
        // This checks if the user is trying to insert the root node at "/" too
        if (nodeDao.listNode(path).isPresent()) {
            throw new DuplicateNodeException(path);
        }

        // Retrieve parent node 
        Node parentNode = nodeDao.listNode(getParentPath(path))
                .orElseThrow(() -> new ContainerNotFoundException(getParentPath(path)));

        // Check if parent node is not a Container node and in case throw
        // appropriate exception
        if (!parentNode.getType().equals("vos:ContainerNode")) {
            if (parentNode.getType().equals("vos:LinkNode")) {
                throw new LinkFoundException(getParentPath(path));
            } else {
                throw new ContainerNotFoundException(getParentPath(path));
            }
        }

        if (!NodeUtils.checkIfWritable(parentNode, principal.getName(), principal.getGroups())) {
            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);
            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);
            }
        }

        // If payload has no read groups specified, inherit from parent node
        String payloadReadGroups = NodeProperties.getNodePropertyByURI(
                node, NodeProperties.GROUP_READ_URI);

        if (payloadReadGroups == null) {
            String parentNodeReadGroups = NodeProperties.getNodePropertyByURI(
                    parentNode, NodeProperties.GROUP_READ_URI);
            if (parentNodeReadGroups != null) {
                Property readGroups = new Property();
                readGroups.setUri(NodeProperties.GROUP_READ_URI);
                readGroups.setValue(parentNodeReadGroups);
                node.getProperties().add(readGroups);
            }
        }

        // If payload has no write groups specified, inherit from parent node
        String payloadWriteGroups = NodeProperties.getNodePropertyByURI(
                node, NodeProperties.GROUP_WRITE_URI);

        if (payloadWriteGroups == null) {
            String parentNodeWriteGroups = NodeProperties.getNodePropertyByURI(
                    parentNode, NodeProperties.GROUP_WRITE_URI);
            if (parentNodeWriteGroups != null) {
                Property writeGroups = new Property();
                writeGroups.setUri(NodeProperties.GROUP_WRITE_URI);
                writeGroups.setValue(parentNodeWriteGroups);
                node.getProperties().add(writeGroups);
            }
        }
        nodeDao.createNode(node);

Sara Bertocco's avatar
Sara Bertocco committed
    }
    // Assuming that this service implementation uses only ! as a separator
    // in the authority part of the URI
    private boolean isValidURI(String nodeURI) {
            parsedAuthority = nodeURI.replaceAll("vos://", "").split("/", -1)[0];

        if (parsedAuthority.isEmpty()
                || !parsedAuthority.replace("~", "!").equals(authority)) {
    }

    private boolean isUrlConsistentWithPayloadURI(String nodeURI, String path) {
        // It's assumed that nodeURI has been validated to be in the expected 
        // form vos://authority[!~]somepath/mynode..."

        return nodeURI.replaceAll("vos://[^/]+", "").equals(path);
    }
Sara Bertocco's avatar
Sara Bertocco committed
}