Skip to content
Snippets Groups Projects
Commit 35b451bf authored by Nicola Fulvio Calabria's avatar Nicola Fulvio Calabria
Browse files

Added LinkNodes management to PullFromVoSpace

parent bd64b755
Branches
Tags
No related merge requests found
......@@ -49,6 +49,9 @@ public class UriService {
@Value("${file-service-url}")
private String fileServiceUrl;
@Value("${link-max-depth}")
private int linkMaxDepth;
@Autowired
private NodeDAO nodeDao;
......@@ -175,6 +178,8 @@ public class UriService {
break;
case pullFromVoSpace:
// Refresh relative path: it can differ in case of links
relativePath = NodeUtils.getVosPath(node);
if (!NodeUtils.checkIfReadable(node, creator, groups)) {
throw PermissionDeniedException.forPath(relativePath);
}
......@@ -278,9 +283,25 @@ public class UriService {
}
private Node followLink(LinkNode linkNode) {
return this.followLinkRecursive(linkNode, 0);
}
private Node followLinkRecursive(LinkNode linkNode, int depth) {
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> targetNode = nodeDao.listNode(targetPath);
return targetNode.orElseThrow(() -> new InternalFaultException("Broken Link to target: " + targetPath));
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;
}
}
}
......@@ -18,4 +18,7 @@ logging.level.org.springframework.web=TRACE
vospace-authority=example.com!vospace
#tune max depth for chained links
link-max-depth=10
file-service-url=http://localhost:8087
......@@ -114,7 +114,7 @@ public class TransferControllerTest {
@Test
public void testPullFromVoSpaceSync() throws Exception {
Node node = mockPublicDataNode();
Node node = mockPublicDataNode("vos://example.com!vospace/mynode");
when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(node));
String requestBody = getResourceFileContent("pullFromVoSpace.xml");
......@@ -198,7 +198,7 @@ public class TransferControllerTest {
private void testVoSpaceAsyncTransfer(String path, String requestBody) throws Exception {
Node node = mockPublicDataNode();
Node node = mockPublicDataNode(path);
when(nodeDao.listNode(eq(path))).thenReturn(Optional.of(node));
String redirect = mockMvc.perform(post("/transfers?PHASE=RUN")
......@@ -216,7 +216,7 @@ public class TransferControllerTest {
@Test
public void testSetJobPhase() throws Exception {
Node node = mockPublicDataNode();
Node node = mockPublicDataNode("vos://example.com!vospace/mynode");
when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(node));
JobSummary job = getFakePendingJob();
......@@ -268,8 +268,9 @@ public class TransferControllerTest {
assertEquals("PENDING", phase);
}
private Node mockPublicDataNode() {
private Node mockPublicDataNode(String nodeURI) {
Node node = new DataNode();
node.setUri(nodeURI);
Property property = new Property();
property.setUri("ivo://ivoa.net/vospace/core#publicread");
property.setValue("true");
......@@ -415,7 +416,7 @@ public class TransferControllerTest {
@Test
public void testSyncTransferUrlParamsMode() throws Exception {
Node node = mockPublicDataNode();
Node node = mockPublicDataNode("vos://example.com!vospace/mynode");
when(nodeDao.listNode(eq("/mynode"))).thenReturn(Optional.of(node));
mockMvc.perform(get("/synctrans")
......
......@@ -8,7 +8,9 @@ package it.inaf.oats.vospace;
import it.inaf.ia2.aa.ServletRapClient;
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.datamodel.Views;
import it.inaf.oats.vospace.exception.InternalFaultException;
import it.inaf.oats.vospace.exception.InvalidArgumentException;
import it.inaf.oats.vospace.exception.NodeBusyException;
import it.inaf.oats.vospace.exception.PermissionDeniedException;
......@@ -22,6 +24,7 @@ import javax.servlet.http.HttpServletRequest;
import net.ivoa.xml.uws.v1.JobSummary;
import net.ivoa.xml.vospace.v2.ContainerNode;
import net.ivoa.xml.vospace.v2.DataNode;
import net.ivoa.xml.vospace.v2.LinkNode;
import net.ivoa.xml.vospace.v2.Node;
import net.ivoa.xml.vospace.v2.Param;
import net.ivoa.xml.vospace.v2.Property;
......@@ -102,7 +105,10 @@ public class UriServiceTest {
@Test
public void testPublicUrl() {
String dataUri = "vos://example.com!vospace/mydata1";
Node node = new DataNode();
node.setUri(dataUri);
Property property = new Property();
property.setUri(NodeProperties.PUBLIC_READ_URI);
property.setValue("true");
......@@ -119,7 +125,10 @@ public class UriServiceTest {
@Test
public void testPrivateUrl() {
String dataUri = "vos://example.com!vospace/mydata1";
Node node = new DataNode();
node.setUri(dataUri);
Property creator = new Property();
creator.setUri(NodeProperties.CREATOR_URI);
creator.setValue("user1");
......@@ -154,7 +163,10 @@ public class UriServiceTest {
@Test
public void testPrivateUrlPermissionDenied() {
String dataUri = "vos://example.com!vospace/mydata1";
Node node = new DataNode();
node.setUri(dataUri);
Property creator = new Property();
creator.setUri(NodeProperties.CREATOR_URI);
creator.setValue("user3");
......@@ -188,8 +200,10 @@ public class UriServiceTest {
@Test
public void testPrivateUrlNodeBusy() {
String dataUri = "vos://example.com!vospace/mydata1";
DataNode node = new DataNode();
node.setUri(dataUri);
Property creator = new Property();
creator.setUri(NodeProperties.CREATOR_URI);
creator.setValue("user1");
......@@ -275,6 +289,114 @@ public class UriServiceTest {
assertEquals("http://file-service/mydata1/mydata2?jobId=job-id2&token=<new-token>", negotiatedTransfer.getProtocols().get(0).getEndpoint());
}
@Test
public void pullFromLinkNode() {
// URI of pull target node
String targetOfPull = "vos://example.com!vospace/mylink1";
String targetOfLink = "vos://example.com!vospace/mydummydata1";
// Define node properties
Property creator = new Property();
creator.setUri(NodeProperties.CREATOR_URI);
creator.setValue("user1");
Property readgroup = new Property();
readgroup.setUri(NodeProperties.GROUP_READ_URI);
readgroup.setValue("group1");
// Define link node as target
LinkNode lnode = new LinkNode();
lnode.setUri(targetOfPull);
lnode.getProperties().add(creator);
lnode.getProperties().add(readgroup);
lnode.setTarget(targetOfLink);
DataNode dnode = new DataNode();
dnode.setUri(targetOfLink);
dnode.getProperties().add(creator);
dnode.getProperties().add(readgroup);
when(nodeDAO.listNode(eq(NodeUtils.getVosPath(lnode)))).thenReturn(Optional.of(lnode));
when(nodeDAO.listNode(eq(NodeUtils.getVosPath(dnode)))).thenReturn(Optional.of(dnode));
User user = mock(User.class);
when(user.getAccessToken()).thenReturn("<token>");
when(user.getName()).thenReturn("user1");
when(servletRequest.getUserPrincipal()).thenReturn(user);
when(rapClient.exchangeToken(argThat(req -> {
assertEquals("<token>", req.getSubjectToken());
assertEquals("http://file-service/mydummydata1", req.getResource());
return true;
}), any())).thenReturn("<new-token>");
JobSummary job = getPullFromVoSpaceJob(targetOfPull);
Transfer tr = uriService.getTransfer(job);
Transfer negotiatedTransfer = uriService.getNegotiatedTransfer(job, tr);
assertEquals("http://file-service"
+ NodeUtils.getVosPath(dnode) +
"?jobId=job-id-pull&token=<new-token>",
negotiatedTransfer.getProtocols().get(0).getEndpoint());
}
@Test
public void pullFromCircularLinkNode() {
// URI of pull target node
String targetOfPull = "vos://example.com!vospace/mylink1";
String targetOfLink = "vos://example.com!vospace/mylink2";
// Define node properties
Property creator = new Property();
creator.setUri(NodeProperties.CREATOR_URI);
creator.setValue("user1");
Property readgroup = new Property();
readgroup.setUri(NodeProperties.GROUP_READ_URI);
readgroup.setValue("group1");
// Define link node as target
LinkNode lnode = new LinkNode();
lnode.setUri(targetOfPull);
lnode.getProperties().add(creator);
lnode.getProperties().add(readgroup);
lnode.setTarget(targetOfLink);
LinkNode dnode = new LinkNode();
dnode.setUri(targetOfLink);
dnode.getProperties().add(creator);
dnode.getProperties().add(readgroup);
// Circular reference
dnode.setTarget(targetOfPull);
when(nodeDAO.listNode(eq(NodeUtils.getVosPath(lnode)))).thenReturn(Optional.of(lnode));
when(nodeDAO.listNode(eq(NodeUtils.getVosPath(dnode)))).thenReturn(Optional.of(dnode));
User user = mock(User.class);
when(user.getAccessToken()).thenReturn("<token>");
when(user.getName()).thenReturn("user1");
when(servletRequest.getUserPrincipal()).thenReturn(user);
when(rapClient.exchangeToken(argThat(req -> {
assertEquals("<token>", req.getSubjectToken());
assertEquals("http://file-service/mydummydata1", req.getResource());
return true;
}), any())).thenReturn("<new-token>");
JobSummary job = getPullFromVoSpaceJob(targetOfPull);
Transfer tr = uriService.getTransfer(job);
assertThrows(InternalFaultException.class, () -> {
uriService.getNegotiatedTransfer(job, tr);
});
}
@Test
public void setNodeRemoteLocationTest() {
......@@ -526,4 +648,23 @@ public class UriServiceTest {
return job;
}
private JobSummary getPullFromVoSpaceJob(String target) {
Transfer transfer = new Transfer();
transfer.setTarget(target);
transfer.setDirection(JobService.JobDirection.pullFromVoSpace.toString());
Protocol protocol = new Protocol();
protocol.setUri("ivo://ivoa.net/vospace/core#httpget");
transfer.getProtocols().add(protocol);
JobSummary job = new JobSummary();
job.setJobId("job-id-pull");
JobSummary.JobInfo jobInfo = new JobSummary.JobInfo();
jobInfo.getAny().add(transfer);
job.setJobInfo(jobInfo);
return job;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment