From c5e4fcb8da46936e0e28699d1bd890925573ace8 Mon Sep 17 00:00:00 2001 From: Nicola Fulvio Calabria <nicola.calabria@inaf.it> Date: Wed, 6 Oct 2021 23:04:04 +0200 Subject: [PATCH] Added external link logic to URIService --- .../oats/vospace/CreateNodeController.java | 1 - .../java/it/inaf/oats/vospace/URIUtils.java | 7 ++ .../java/it/inaf/oats/vospace/UriService.java | 72 ++++++++++++------- .../vospace/persistence/LinkedServiceDAO.java | 2 +- .../it/inaf/oats/vospace/URIUtilsTest.java | 8 +++ 5 files changed, 63 insertions(+), 27 deletions(-) diff --git a/src/main/java/it/inaf/oats/vospace/CreateNodeController.java b/src/main/java/it/inaf/oats/vospace/CreateNodeController.java index 4cd2860..7a6e047 100644 --- a/src/main/java/it/inaf/oats/vospace/CreateNodeController.java +++ b/src/main/java/it/inaf/oats/vospace/CreateNodeController.java @@ -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; diff --git a/src/main/java/it/inaf/oats/vospace/URIUtils.java b/src/main/java/it/inaf/oats/vospace/URIUtils.java index 0250050..36bd239 100644 --- a/src/main/java/it/inaf/oats/vospace/URIUtils.java +++ b/src/main/java/it/inaf/oats/vospace/URIUtils.java @@ -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; diff --git a/src/main/java/it/inaf/oats/vospace/UriService.java b/src/main/java/it/inaf/oats/vospace/UriService.java index 056aa04..6f78cb1 100644 --- a/src/main/java/it/inaf/oats/vospace/UriService.java +++ b/src/main/java/it/inaf/oats/vospace/UriService.java @@ -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; @@ -58,6 +59,9 @@ public class UriService { @Autowired private LocationDAO locationDAO; + @Autowired + private LinkedServiceDAO linkedServiceDAO; + @Autowired private HttpServletRequest servletRequest; @@ -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: @@ -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); @@ -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); } @@ -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; + } } } } diff --git a/src/main/java/it/inaf/oats/vospace/persistence/LinkedServiceDAO.java b/src/main/java/it/inaf/oats/vospace/persistence/LinkedServiceDAO.java index e8adf2f..5af9910 100644 --- a/src/main/java/it/inaf/oats/vospace/persistence/LinkedServiceDAO.java +++ b/src/main/java/it/inaf/oats/vospace/persistence/LinkedServiceDAO.java @@ -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 || '%'"; diff --git a/src/test/java/it/inaf/oats/vospace/URIUtilsTest.java b/src/test/java/it/inaf/oats/vospace/URIUtilsTest.java index d630f85..6897ae5 100644 --- a/src/test/java/it/inaf/oats/vospace/URIUtilsTest.java +++ b/src/test/java/it/inaf/oats/vospace/URIUtilsTest.java @@ -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 { @@ -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")); + } } -- GitLab