Commit cd274712 authored by Nicola Fulvio Calabria's avatar Nicola Fulvio Calabria
Browse files

Implemented style fixes

parent 5aa1b9b8
Loading
Loading
Loading
Loading
+1 −6
Original line number Original line Diff line number Diff line
@@ -16,11 +16,6 @@ public abstract class BaseNodeController {
    private HttpServletRequest servletRequest;
    private HttpServletRequest servletRequest;


    protected String getPath() {       
    protected String getPath() {       
        // This is to allow calls from the code to CreateNodeController
        // since request url is not set
        if(servletRequest.getRequestURL() == null)
            return null;
        
        String requestURL = servletRequest.getRequestURL().toString();
        String requestURL = servletRequest.getRequestURL().toString();
        try {
        try {
            return NodeUtils.getPathFromRequestURLString(requestURL);
            return NodeUtils.getPathFromRequestURLString(requestURL);
+4 −122
Original line number Original line Diff line number Diff line
@@ -27,137 +27,19 @@ public class CreateNodeController extends BaseNodeController {
    private static final Logger LOG = LoggerFactory.getLogger(CreateNodeController.class);
    private static final Logger LOG = LoggerFactory.getLogger(CreateNodeController.class);


    @Autowired
    @Autowired
    private NodeDAO nodeDao;
    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})
    public Node createNode(@RequestBody Node node, User principal) {
    public Node createNode(@RequestBody Node node, User principal) {


        LOG.debug("createNode called for node with URI {}", node.getUri());
        String path = getPath();
        
        // Validate payload node URI
        if (!isValidURI(node.getUri())) {
            throw new InvalidURIException(node.getUri());
        }        
        
        String path;        
        
        if(getPath() == null) {
            LOG.debug("createNode called internally with null path");
            path = node.getUri().replaceAll("vos://[^/]+", "");
        } else {            
            path = getPath();
            LOG.debug("createNode called for path {}", path);
        }

        // 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 
        LOG.debug("createNodeController called for node with URI {} and PATH {}", node.getUri(), path);
        Node parentNode = nodeDao.listNode(getParentPath(path))
                .orElseThrow(() -> new ContainerNotFoundException(getParentPath(path)));


        // Check if parent node is not a Container node and in case throw
        return createNodeService.createNode(node, path, principal);
        // 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);

        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);
            }
        }

        // 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);

        return node;
    }

    // Assuming that this service implementation uses only ! as a separator
    // in the authority part of the URI
    private boolean isValidURI(String nodeURI) {
        String parsedAuthority;
        if (!nodeURI.startsWith("vos://")) {
            return false;
        } else {
            parsedAuthority = nodeURI.replaceAll("vos://", "").split("/", -1)[0];
        }

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

        return true;
    }

    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);
    }
}
}
+159 −0
Original line number Original line Diff line number Diff line
/*
 * This file is part of vospace-rest
 * Copyright (C) 2021 Istituto Nazionale di Astrofisica
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
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.DuplicateNodeException;
import it.inaf.oats.vospace.exception.InvalidURIException;
import it.inaf.oats.vospace.exception.LinkFoundException;
import it.inaf.oats.vospace.exception.PermissionDeniedException;
import it.inaf.oats.vospace.persistence.NodeDAO;
import javax.servlet.http.HttpServletRequest;
import net.ivoa.xml.vospace.v2.Node;
import net.ivoa.xml.vospace.v2.Property;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Service
@EnableTransactionManagement
public class CreateNodeService {

    @Autowired
    private NodeDAO nodeDao;

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

    private static final Logger LOG = LoggerFactory.getLogger(CreateNodeService.class);

    public Node createNode(Node node, String path, User principal) {
        
        LOG.debug("createNodeService called for node with URI {} and PATH {}", node.getUri(), path);
        
        // Validate payload node URI
        if (!isValidURI(node.getUri())) {
            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);

        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);
            }
        }

        // 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);

        return node;

    }

    // Assuming that this service implementation uses only ! as a separator
    // in the authority part of the URI
    private boolean isValidURI(String nodeURI) {
        String parsedAuthority;
        if (!nodeURI.startsWith("vos://")) {
            return false;
        } else {
            parsedAuthority = nodeURI.replaceAll("vos://", "").split("/", -1)[0];
        }

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

        return true;
    }

    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);
    }
    
    private String getParentPath(String path) {
        return NodeUtils.getParentPath(path);
    }    
}
+3 −5
Original line number Original line Diff line number Diff line
@@ -35,9 +35,6 @@ public class MoveService {
    @Value("${vospace-authority}")
    @Value("${vospace-authority}")
    private String authority;
    private String authority;
    
    
    @Autowired
    private CreateNodeController createNodeController;

    @Autowired
    @Autowired
    private HttpServletRequest servletRequest;
    private HttpServletRequest servletRequest;
    
    
@@ -114,6 +111,7 @@ public class MoveService {
        return optNodeId.isPresent();
        return optNodeId.isPresent();
    }
    }
    
    
    /*
    // Returns node id of created destination
    // Returns node id of created destination
    private Long createDestination(String path, User user) {
    private Long createDestination(String path, User user) {
        List<String> components = NodeUtils.subPathComponents(path);
        List<String> components = NodeUtils.subPathComponents(path);
@@ -129,6 +127,6 @@ public class MoveService {
        return nodeDao.getNodeId(path).orElseThrow(()-> 
        return nodeDao.getNodeId(path).orElseThrow(()-> 
                new InternalFaultException("Unable to create destination at path: "+path));
                new InternalFaultException("Unable to create destination at path: "+path));
            
            
    }
    }*/


}
}
+3 −3
Original line number Original line Diff line number Diff line
@@ -61,7 +61,7 @@ public class UriService {
    private ServletRapClient rapClient;
    private ServletRapClient rapClient;


    @Autowired
    @Autowired
    private CreateNodeController createNodeController;
    private CreateNodeService createNodeService;


    public void setTransferJobResult(JobSummary job, Transfer transfer) {
    public void setTransferJobResult(JobSummary job, Transfer transfer) {


@@ -134,8 +134,8 @@ public class UriService {
                case pushToVoSpace:
                case pushToVoSpace:
                case pullToVoSpace:
                case pullToVoSpace:
                    DataNode newNode = new DataNode();
                    DataNode newNode = new DataNode();
                    newNode.setUri(relativePath);
                    newNode.setUri("vos://"+ authority +relativePath);
                    return createNodeController.createNode(newNode, user);
                    return createNodeService.createNode(newNode, relativePath, user);
                default:
                default:
                    throw new InternalFaultException("No supported job direction specified");
                    throw new InternalFaultException("No supported job direction specified");
            }
            }
Loading