Loading src/main/java/it/inaf/oats/vospace/CreateNodeController.java +0 −1 Original line number Diff line number Diff line Loading @@ -6,7 +6,6 @@ package it.inaf.oats.vospace; import it.inaf.ia2.aa.data.User; import it.inaf.oats.vospace.exception.InvalidURIException; import net.ivoa.xml.vospace.v2.LinkNode; import net.ivoa.xml.vospace.v2.Node; import org.springframework.http.MediaType; Loading src/main/java/it/inaf/oats/vospace/URIUtils.java +7 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,13 @@ public class URIUtils { // 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"; public static boolean isURIInternal(String URI) { if(URI == null) throw new IllegalArgumentException("URI can't be null"); return URI.toLowerCase().startsWith(SCHEME); } public static String returnURIFromVosPath(String vosPath, String authority) { String result = null; Loading src/main/java/it/inaf/oats/vospace/UriService.java +47 −25 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ import it.inaf.oats.vospace.exception.NodeNotFoundException; import it.inaf.oats.vospace.exception.PermissionDeniedException; import it.inaf.oats.vospace.exception.ProtocolNotSupportedException; import it.inaf.oats.vospace.exception.NodeBusyException; import it.inaf.oats.vospace.persistence.LinkedServiceDAO; import it.inaf.oats.vospace.persistence.LocationDAO; import it.inaf.oats.vospace.persistence.NodeDAO; import it.inaf.oats.vospace.persistence.model.Location; Loading Loading @@ -58,6 +59,9 @@ public class UriService { @Autowired private LocationDAO locationDAO; @Autowired private LinkedServiceDAO linkedServiceDAO; @Autowired private HttpServletRequest servletRequest; Loading Loading @@ -168,7 +172,7 @@ public class UriService { JobService.JobDirection jobType = JobDirection.getJobDirectionEnumFromTransfer(transfer); Node node = this.getEndpointNode(relativePath, jobType, user); switch (jobType) { case pushToVoSpace: case pullToVoSpace: Loading @@ -178,7 +182,7 @@ public class UriService { break; case pullFromVoSpace: // Refresh relative path: it can differ in case of links // Refresh relative path: it can differ in case of links followed relativePath = NodeUtils.getVosPath(node); if (!NodeUtils.checkIfReadable(node, creator, groups)) { throw PermissionDeniedException.forPath(relativePath); Loading @@ -197,24 +201,36 @@ public class UriService { return fileServiceClient.startArchiveJob(transfer, job.getJobId()); } Location location = locationDAO.getNodeLocation(relativePath).orElse(null); boolean isLinkNode = node instanceof LinkNode; String endpoint; if (location != null && location.getType() == LocationType.PORTAL) { String fileName = nodeDao.getNodeOsName(relativePath); endpoint = "http://" + location.getSource().getHostname() + location.getSource().getBaseUrl(); if (!endpoint.endsWith("/")) { endpoint += "/"; } endpoint += fileName; if (isLinkNode) { endpoint = ((LinkNode) node).getTarget(); } else { endpoint = fileServiceUrl + urlEncodePath(relativePath); Location location = locationDAO.getNodeLocation(relativePath).orElse(null); if (location != null && location.getType() == LocationType.PORTAL) { String fileName = nodeDao.getNodeOsName(relativePath); endpoint = "http://" + location.getSource().getHostname() + location.getSource().getBaseUrl(); if (!endpoint.endsWith("/")) { endpoint += "/"; } endpoint += fileName; } else { endpoint = fileServiceUrl + urlEncodePath(relativePath); } } endpoint += "?jobId=" + job.getJobId(); if (!"true".equals(NodeProperties.getNodePropertyByURI(node, NodeProperties.PUBLIC_READ_URI))) { if (isLinkNode) { String linkTarget = ((LinkNode) node).getTarget(); if (linkedServiceDAO.isLinkedServiceUrl(linkTarget)) { endpoint += "&token=" + getEndpointToken(linkTarget); } } else if (!"true".equals(NodeProperties.getNodePropertyByURI(node, NodeProperties.PUBLIC_READ_URI))) { endpoint += "&token=" + getEndpointToken(fileServiceUrl + relativePath); } Loading Loading @@ -287,21 +303,27 @@ public class UriService { } private Node followLinkRecursive(LinkNode linkNode, int depth) { if(depth >= linkMaxDepth) { throw new InternalFaultException("Max link depth reached at link node: " if (depth >= linkMaxDepth) { throw new InternalFaultException("Max link depth reached at link node: " + NodeUtils.getVosPath(linkNode)); } String targetPath = URIUtils.returnVosPathFromNodeURI(linkNode.getTarget(), authority); Optional<Node> targetNodeOpt = nodeDao.listNode(targetPath); Node targetNode = targetNodeOpt.orElseThrow(() -> new InternalFaultException("Broken Link to target: " + targetPath)); if(targetNode instanceof LinkNode) { return this.followLinkRecursive(linkNode, ++depth); } else { return targetNode; String linkTarget = linkNode.getTarget(); if (URIUtils.isURIInternal(linkTarget)) { return linkNode; } else { String targetPath = URIUtils.returnVosPathFromNodeURI(linkTarget, authority); Optional<Node> targetNodeOpt = nodeDao.listNode(targetPath); Node targetNode = targetNodeOpt.orElseThrow(() -> new InternalFaultException("Broken Link to target: " + targetPath)); if (targetNode instanceof LinkNode) { return this.followLinkRecursive(linkNode, ++depth); } else { return targetNode; } } } } src/main/java/it/inaf/oats/vospace/persistence/LinkedServiceDAO.java +1 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ public class LinkedServiceDAO { jdbcTemplate = new JdbcTemplate(dataSource); } boolean isLinkedServiceUrl(String targetUrl) { public boolean isLinkedServiceUrl(String targetUrl) { String sql = " SELECT COUNT(*) > 0\n" + "FROM linked_service\n" + "WHERE ? LIKE service_base_url || '%'"; Loading src/test/java/it/inaf/oats/vospace/URIUtilsTest.java +8 −0 Original line number Diff line number Diff line Loading @@ -8,7 +8,9 @@ package it.inaf.oats.vospace; import it.inaf.oats.vospace.exception.InvalidURIException; import java.net.URISyntaxException; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; public class URIUtilsTest { Loading Loading @@ -84,6 +86,12 @@ public class URIUtilsTest { String test3 = URIUtils.returnURIFromVosPath("/test1/te# !?st2", authority); assertEquals("vos://"+authority+"/test1/te%23%20!%3Fst2", test3); } @Test public void testIsURIInternal() { assertTrue(URIUtils.isURIInternal("vos://"+authority+"/test1/test2")); assertFalse(URIUtils.isURIInternal("http://host.ia2.inaf.it/test1/test2")); } } Loading
src/main/java/it/inaf/oats/vospace/CreateNodeController.java +0 −1 Original line number Diff line number Diff line Loading @@ -6,7 +6,6 @@ package it.inaf.oats.vospace; import it.inaf.ia2.aa.data.User; import it.inaf.oats.vospace.exception.InvalidURIException; import net.ivoa.xml.vospace.v2.LinkNode; import net.ivoa.xml.vospace.v2.Node; import org.springframework.http.MediaType; Loading
src/main/java/it/inaf/oats/vospace/URIUtils.java +7 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,13 @@ public class URIUtils { // 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"; public static boolean isURIInternal(String URI) { if(URI == null) throw new IllegalArgumentException("URI can't be null"); return URI.toLowerCase().startsWith(SCHEME); } public static String returnURIFromVosPath(String vosPath, String authority) { String result = null; Loading
src/main/java/it/inaf/oats/vospace/UriService.java +47 −25 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ import it.inaf.oats.vospace.exception.NodeNotFoundException; import it.inaf.oats.vospace.exception.PermissionDeniedException; import it.inaf.oats.vospace.exception.ProtocolNotSupportedException; import it.inaf.oats.vospace.exception.NodeBusyException; import it.inaf.oats.vospace.persistence.LinkedServiceDAO; import it.inaf.oats.vospace.persistence.LocationDAO; import it.inaf.oats.vospace.persistence.NodeDAO; import it.inaf.oats.vospace.persistence.model.Location; Loading Loading @@ -58,6 +59,9 @@ public class UriService { @Autowired private LocationDAO locationDAO; @Autowired private LinkedServiceDAO linkedServiceDAO; @Autowired private HttpServletRequest servletRequest; Loading Loading @@ -168,7 +172,7 @@ public class UriService { JobService.JobDirection jobType = JobDirection.getJobDirectionEnumFromTransfer(transfer); Node node = this.getEndpointNode(relativePath, jobType, user); switch (jobType) { case pushToVoSpace: case pullToVoSpace: Loading @@ -178,7 +182,7 @@ public class UriService { break; case pullFromVoSpace: // Refresh relative path: it can differ in case of links // Refresh relative path: it can differ in case of links followed relativePath = NodeUtils.getVosPath(node); if (!NodeUtils.checkIfReadable(node, creator, groups)) { throw PermissionDeniedException.forPath(relativePath); Loading @@ -197,24 +201,36 @@ public class UriService { return fileServiceClient.startArchiveJob(transfer, job.getJobId()); } Location location = locationDAO.getNodeLocation(relativePath).orElse(null); boolean isLinkNode = node instanceof LinkNode; String endpoint; if (location != null && location.getType() == LocationType.PORTAL) { String fileName = nodeDao.getNodeOsName(relativePath); endpoint = "http://" + location.getSource().getHostname() + location.getSource().getBaseUrl(); if (!endpoint.endsWith("/")) { endpoint += "/"; } endpoint += fileName; if (isLinkNode) { endpoint = ((LinkNode) node).getTarget(); } else { endpoint = fileServiceUrl + urlEncodePath(relativePath); Location location = locationDAO.getNodeLocation(relativePath).orElse(null); if (location != null && location.getType() == LocationType.PORTAL) { String fileName = nodeDao.getNodeOsName(relativePath); endpoint = "http://" + location.getSource().getHostname() + location.getSource().getBaseUrl(); if (!endpoint.endsWith("/")) { endpoint += "/"; } endpoint += fileName; } else { endpoint = fileServiceUrl + urlEncodePath(relativePath); } } endpoint += "?jobId=" + job.getJobId(); if (!"true".equals(NodeProperties.getNodePropertyByURI(node, NodeProperties.PUBLIC_READ_URI))) { if (isLinkNode) { String linkTarget = ((LinkNode) node).getTarget(); if (linkedServiceDAO.isLinkedServiceUrl(linkTarget)) { endpoint += "&token=" + getEndpointToken(linkTarget); } } else if (!"true".equals(NodeProperties.getNodePropertyByURI(node, NodeProperties.PUBLIC_READ_URI))) { endpoint += "&token=" + getEndpointToken(fileServiceUrl + relativePath); } Loading Loading @@ -287,21 +303,27 @@ public class UriService { } private Node followLinkRecursive(LinkNode linkNode, int depth) { if(depth >= linkMaxDepth) { throw new InternalFaultException("Max link depth reached at link node: " if (depth >= linkMaxDepth) { throw new InternalFaultException("Max link depth reached at link node: " + NodeUtils.getVosPath(linkNode)); } String targetPath = URIUtils.returnVosPathFromNodeURI(linkNode.getTarget(), authority); Optional<Node> targetNodeOpt = nodeDao.listNode(targetPath); Node targetNode = targetNodeOpt.orElseThrow(() -> new InternalFaultException("Broken Link to target: " + targetPath)); if(targetNode instanceof LinkNode) { return this.followLinkRecursive(linkNode, ++depth); } else { return targetNode; String linkTarget = linkNode.getTarget(); if (URIUtils.isURIInternal(linkTarget)) { return linkNode; } else { String targetPath = URIUtils.returnVosPathFromNodeURI(linkTarget, authority); Optional<Node> targetNodeOpt = nodeDao.listNode(targetPath); Node targetNode = targetNodeOpt.orElseThrow(() -> new InternalFaultException("Broken Link to target: " + targetPath)); if (targetNode instanceof LinkNode) { return this.followLinkRecursive(linkNode, ++depth); } else { return targetNode; } } } }
src/main/java/it/inaf/oats/vospace/persistence/LinkedServiceDAO.java +1 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ public class LinkedServiceDAO { jdbcTemplate = new JdbcTemplate(dataSource); } boolean isLinkedServiceUrl(String targetUrl) { public boolean isLinkedServiceUrl(String targetUrl) { String sql = " SELECT COUNT(*) > 0\n" + "FROM linked_service\n" + "WHERE ? LIKE service_base_url || '%'"; Loading
src/test/java/it/inaf/oats/vospace/URIUtilsTest.java +8 −0 Original line number Diff line number Diff line Loading @@ -8,7 +8,9 @@ package it.inaf.oats.vospace; import it.inaf.oats.vospace.exception.InvalidURIException; import java.net.URISyntaxException; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; public class URIUtilsTest { Loading Loading @@ -84,6 +86,12 @@ public class URIUtilsTest { String test3 = URIUtils.returnURIFromVosPath("/test1/te# !?st2", authority); assertEquals("vos://"+authority+"/test1/te%23%20!%3Fst2", test3); } @Test public void testIsURIInternal() { assertTrue(URIUtils.isURIInternal("vos://"+authority+"/test1/test2")); assertFalse(URIUtils.isURIInternal("http://host.ia2.inaf.it/test1/test2")); } }