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

Implemented input node URI validation and decoding + minor refinements

parent 40b6b3b2
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -40,11 +40,13 @@ public class CreateNodeService {
        LOG.debug("createNodeService called for node with URI {} and PATH {}", node.getUri(), path);
        
        // Get Node path (and validates it too)
        String decodedURIFromNode = URIUtils.returnVosPathFromNodeURI(node.getUri(), authority);
        String decodedURIPathFromNode = URIUtils.returnVosPathFromNodeURI(node.getUri(), authority);       
        
        LOG.debug("createNodeService URI: {} decoded as {}", node.getUri(), decodedURIPathFromNode);

        // Check if payload URI is consistent with http request
        if (!decodedURIFromNode.equals(path)) {
            throw new InvalidURIException(decodedURIFromNode, path);
        if (!decodedURIPathFromNode.equals(path)) {
            throw new InvalidURIException(decodedURIPathFromNode, path);
        }

        // Check if another node is already present at specified path
@@ -119,7 +121,7 @@ public class CreateNodeService {
            }
        }
                                
        nodeDao.createNode(node);
        nodeDao.createNode(node, decodedURIPathFromNode);

        return node;

+3 −3
Original line number Diff line number Diff line
@@ -16,11 +16,11 @@ public class URIUtils {
    // It's different from the one in NodeUtils!
    // Slashes are treated separately
    private static final Pattern FORBIDDEN_CHARS = Pattern.compile("[\\x00\\x08\\x0B\\x0C\\x0E-\\x1F" + Pattern.quote("<>?\":\\|'`*") + "]");
    private static final String SCHEME = "vos";

    // This method validates the URI too
    public static String returnVosPathFromNodeURI(String nodeURI, String authority) {
                
        String scheme = "vos";
        String resultPath = null;
        
        try{
@@ -30,7 +30,7 @@ public class URIUtils {
        if(!uri.isAbsolute() || 
                uri.isOpaque() || 
                !uri.getRawSchemeSpecificPart().startsWith("//") ||
                !uri.getScheme().equalsIgnoreCase(scheme))
                !uri.getScheme().equalsIgnoreCase(SCHEME))
            throw new InvalidURIException(nodeURI);
        
        // Check authority
+1 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ public class ErrorSummaryFactory {
        } else {
            result.setHasDetail(true);
            result.setDetailMessage(error.getFaultCaptionForDetails()
                    + ". "
                    + " "
                    + detailMessage);
        }

+5 −3
Original line number Diff line number Diff line
@@ -12,10 +12,12 @@ import org.springframework.web.bind.annotation.ResponseStatus;
public abstract class VoSpaceErrorSummarizableException extends VoSpaceException {
    
    VOSpaceFaultEnum fault;
    private String detailMessage;
    
    public VoSpaceErrorSummarizableException(String message, VOSpaceFaultEnum fault)
    public VoSpaceErrorSummarizableException(String detailMessage, VOSpaceFaultEnum fault)
    {
        super(fault.getFaultCaptionForDetails() +" " + message);
        super(fault.getFaultCaptionForDetails() + " " + detailMessage);
        this.detailMessage = detailMessage;
        this.fault = fault;        
    }
        
@@ -26,6 +28,6 @@ public abstract class VoSpaceErrorSummarizableException extends VoSpaceException
        
    public String getDetailMessage()
    {
        return this.getMessage();
        return this.detailMessage;
    }
}
+6 −109
Original line number Diff line number Diff line
@@ -51,11 +51,10 @@ public class NodeDAO {
        jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public void createNode(Node myNode) {
    public void createNode(Node myNode, String vosPath) {

        String nodeURI = myNode.getUri();        
        String path = nodeURI.replaceAll("vos://[^/]+", "");
        String parentPath = NodeUtils.getParentPath(path);
        String parentPath = NodeUtils.getParentPath(vosPath);

        List<NodePaths> paths = getNodePathsFromDB(nodeURI);

@@ -75,7 +74,7 @@ public class NodeDAO {
        jdbcTemplate.update(conn -> {
            PreparedStatement ps = conn.prepareStatement(sb.toString());
            int i = 0;
            ps.setString(++i, NodeUtils.getNodeName(myNode));
            ps.setString(++i, NodeUtils.getNodeName(vosPath));
            ps.setBoolean(++i, NodeUtils.getIsBusy(myNode));
            ps.setString(++i, NodeProperties.getStandardNodePropertyByName(myNode, "creator"));
            ps.setArray(++i, fromPropertyToArray(ps, NodeProperties.getStandardNodePropertyByName(myNode, "groupread")));
@@ -253,36 +252,11 @@ public class NodeDAO {
        }
    }
 
    /*
    public Optional<String> getLtreePath(String nodeVosPath) {
        String sql = "SELECT path FROM node n "
                + "JOIN node_vos_path p ON n.node_id = p.node_id "
                + "WHERE vos_path = ?";

        List<String> nodeIdList = jdbcTemplate.query(conn -> {
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setString(1, nodeVosPath);
            return ps;
        }, (row, index) -> {
            return row.getString("path");
        });

        switch (nodeIdList.size()) {
            case 0:
                return Optional.empty();

            case 1:
                return Optional.of(nodeIdList.get(0));

            default:
                throw new InternalFaultException("More than 1 node at path: " + nodeVosPath);
        }
    }*/
    public Optional<ShortNodeDescriptor> getShortNodeDescriptor(String nodeVosPath,
            String userId, List<String> userGroups) {
                        
        String sql = "SELECT path,\n"
                + "NOT (n.async_trans OR n.sticky OR loc.location_type = 'async') AS is_writable,\n"
                + "NOT (n.async_trans OR n.sticky OR COALESCE(location_type = 'async', FALSE)) AS is_writable,\n"
                + "((SELECT COUNT(*) FROM (SELECT UNNEST(?) INTERSECT SELECT UNNEST(n.group_write)) AS allowed_groups ) = 0 AND\n"
                + "n.creator_id <> ?) AS is_permission_denied,\n"
                + "n.type = 'container' AS is_container,\n"
@@ -326,83 +300,6 @@ public class NodeDAO {

    }

    /*
    public Optional<Node> getNodeById(Long nodeId, boolean enforceTapeStoredCheck) {
        String sql = "SELECT os.vos_path, loc.location_type, n.node_id, type, async_trans, sticky, busy_state, creator_id, group_read, group_write,\n"
                + "is_public, content_length, created_on, last_modified, accept_views, provide_views\n"
                + "FROM node n\n"
                + "JOIN node_vos_path os ON n.node_id = os.node_id\n"
                + "JOIN location loc ON n.location_id = loc.location_id\n"
                + "WHERE n.node_id = ?\n"
                + "FOR UPDATE";

        List<Node> result = jdbcTemplate.query(conn -> {
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setLong(1, nodeId);
            return ps;
        }, (row, index) -> {
            if (enforceTapeStoredCheck && row.getString("location_type").equals("async")) {
                throw new InternalFaultException(
                        "Node id: " + nodeId + " has async location type. "
                        + "Failure due to enforced check.");
            }
            return getNodeFromResultSet(row);
        });

        switch (result.size()) {
            case 0:
                return Optional.empty();

            case 1:
                return Optional.of(result.get(0));

            default:
                throw new InternalFaultException("Multiple nodes with id: " + nodeId);
        }
    }
     */

 /*
    // First node is the root node 
    public List<Node> listNodesInBranch(Long rootNodeId, boolean enforceTapeStoredCheck) {
        String sql = "SELECT os.vos_path, loc.location_type, n.node_id, type, async_trans, sticky, busy_state, creator_id, group_read, group_write,\n"
                + "is_public, content_length, created_on, last_modified, accept_views, provide_views\n"
                + "FROM node n\n"
                + "JOIN node_vos_path os ON n.node_id = os.node_id\n"
                + "JOIN location loc ON n.location_id = loc.location_id\n"
                + "WHERE n.path ~ ('*.' || ? || '.*')::lquery\n"
                + "ORDER BY n.path FOR UPDATE";

        List<Node> result = jdbcTemplate.query(conn -> {
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setString(1, Long.toString(rootNodeId));
            return ps;
        }, (row, index) -> {
            if (enforceTapeStoredCheck && row.getString("location_type").equals("async")) {
                throw new InternalFaultException(
                        "At least one node in branch with root id: " + rootNodeId
                        + " has async location type. "
                        + "Failure due to enforced check.");
            }
            return getNodeFromResultSet(row);
        });

        return result;

    }*/

 /*
    public void setBranchBusy(Long rootNodeId, boolean busyState) {
        String sql = "UPDATE node SET busy_state = ?\n"
                + "WHERE path ~ ('*.' || ? || '.*')::lquery";

        jdbcTemplate.update(conn -> {
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setBoolean(1, busyState);
            ps.setLong(2, rootNodeId);
            return ps;
        });
    }*/
    public void renameNode(Long nodeId, String name) {
        String sql = "UPDATE node SET name = ?\n"
                + "WHERE path ~ ('*.' || ?)::lquery";
Loading