Loading src/main/java/it/inaf/oats/vospace/FileServiceClient.java +30 −4 Original line number Original line Diff line number Diff line Loading @@ -7,6 +7,8 @@ package it.inaf.oats.vospace; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper; import it.inaf.ia2.aa.data.User; import it.inaf.ia2.aa.data.User; import it.inaf.oats.vospace.datamodel.Views; import it.inaf.oats.vospace.exception.InvalidArgumentException; import java.io.OutputStream; import java.io.OutputStream; import java.util.List; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Collectors; Loading Loading @@ -39,8 +41,32 @@ public class FileServiceClient { public String startArchiveJob(Transfer transfer, String jobId) { public String startArchiveJob(Transfer transfer, String jobId) { List<String> vosPaths = transfer.getTarget().stream() if (transfer.getTarget().size() != 1) { .map(p -> p.substring("vos://".length() + authority.length())).collect(Collectors.toList()); throw new IllegalArgumentException("Target size is " + transfer.getTarget().size()); } String target = transfer.getTarget().get(0); String viewUri = transfer.getView().getUri(); // Generate list of paths using view include parameters List<String> vosPaths = transfer.getView().getParam().stream() .map(p -> { if (p.getUri().equals(viewUri + "/include")) { if (p.getValue().contains("../")) { throw new InvalidArgumentException("Relative paths are not supported"); } return target + "/" + p.getValue(); } else { throw new InvalidArgumentException("Unsupported view parameter: " + p.getUri()); } }) .collect(Collectors.toList()); if (vosPaths.isEmpty()) { // Add target path vosPaths.add(target.substring("vos://".length() + authority.length())); } ArchiveRequest archiveRequest = new ArchiveRequest(); ArchiveRequest archiveRequest = new ArchiveRequest(); archiveRequest.setJobId(jobId); archiveRequest.setJobId(jobId); Loading Loading @@ -98,9 +124,9 @@ public class FileServiceClient { private static String archiveTypeFromViewUri(String viewUri) { private static String archiveTypeFromViewUri(String viewUri) { switch (viewUri) { switch (viewUri) { case "ivo://ia2.inaf.it/vospace/views#tar": case Views.TAR_VIEW_URI: return "TAR"; return "TAR"; case "ivo://ia2.inaf.it/vospace/views#zip": case Views.ZIP_VIEW_URI: return "ZIP"; return "ZIP"; default: default: throw new IllegalArgumentException("Archive type not defined for " + viewUri); throw new IllegalArgumentException("Archive type not defined for " + viewUri); Loading src/test/java/it/inaf/oats/vospace/FileServiceClientTest.java +68 −1 Original line number Original line Diff line number Diff line Loading @@ -7,13 +7,16 @@ package it.inaf.oats.vospace; import it.inaf.ia2.aa.data.User; import it.inaf.ia2.aa.data.User; import it.inaf.oats.vospace.datamodel.Views; import it.inaf.oats.vospace.datamodel.Views; import it.inaf.oats.vospace.exception.InvalidArgumentException; import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream; import java.net.URI; import java.net.URI; import java.util.Arrays; import java.util.Arrays; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest; import net.ivoa.xml.vospace.v2.Param; import net.ivoa.xml.vospace.v2.Transfer; import net.ivoa.xml.vospace.v2.Transfer; import net.ivoa.xml.vospace.v2.View; import net.ivoa.xml.vospace.v2.View; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test; Loading Loading @@ -75,15 +78,79 @@ public class FileServiceClientTest { } } } } @Test public void testArchiveNoInclude() { Transfer transfer = new Transfer(); transfer.setDirection("pullFromVoSpace"); transfer.setTarget(Arrays.asList("vos://example.com!vospace/mydir")); View view = new View(); view.setUri(Views.ZIP_VIEW_URI); transfer.setView(view); testStartArchiveJob(transfer); } @Test public void testInvalidViewParam() { Transfer transfer = new Transfer(); transfer.setDirection("pullFromVoSpace"); transfer.setTarget(Arrays.asList("vos://example.com!vospace/parent_dir")); View view = new View(); view.setUri(Views.TAR_VIEW_URI); transfer.setView(view); Param param1 = new Param(); param1.setUri("invalid"); param1.setValue("file1"); view.getParam().add(param1); assertThrows(InvalidArgumentException.class, () -> testStartArchiveJob(transfer)); } @Test public void testInvalidViewParamPath() { Transfer transfer = new Transfer(); transfer.setDirection("pullFromVoSpace"); transfer.setTarget(Arrays.asList("vos://example.com!vospace/parent_dir")); View view = new View(); view.setUri(Views.TAR_VIEW_URI); transfer.setView(view); Param param1 = new Param(); param1.setUri(Views.TAR_VIEW_URI + "/include"); param1.setValue("../file1"); view.getParam().add(param1); assertThrows(InvalidArgumentException.class, () -> testStartArchiveJob(transfer)); } private void testStartArchiveJob(String viewUri) { private void testStartArchiveJob(String viewUri) { Transfer transfer = new Transfer(); Transfer transfer = new Transfer(); transfer.setDirection("pullFromVoSpace"); transfer.setDirection("pullFromVoSpace"); transfer.setTarget(Arrays.asList("vos://example.com!vospace/file1", "vos://example.com!vospace/file2")); transfer.setTarget(Arrays.asList("vos://example.com!vospace/parent_dir")); View view = new View(); View view = new View(); view.setUri(viewUri); view.setUri(viewUri); transfer.setView(view); transfer.setView(view); Param param1 = new Param(); param1.setUri(viewUri + "/include"); param1.setValue("file1"); view.getParam().add(param1); Param param2 = new Param(); param2.setUri(viewUri + "/include"); param2.setValue("file2"); view.getParam().add(param2); testStartArchiveJob(transfer); } private void testStartArchiveJob(Transfer transfer) { User user = mock(User.class); User user = mock(User.class); when(user.getAccessToken()).thenReturn("<token>"); when(user.getAccessToken()).thenReturn("<token>"); when(request.getUserPrincipal()).thenReturn(user); when(request.getUserPrincipal()).thenReturn(user); Loading src/test/java/it/inaf/oats/vospace/UriServiceTest.java +22 −9 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ import net.ivoa.xml.uws.v1.JobSummary; import net.ivoa.xml.vospace.v2.ContainerNode; import net.ivoa.xml.vospace.v2.ContainerNode; import net.ivoa.xml.vospace.v2.DataNode; import net.ivoa.xml.vospace.v2.DataNode; import net.ivoa.xml.vospace.v2.Node; import net.ivoa.xml.vospace.v2.Node; import net.ivoa.xml.vospace.v2.Param; import net.ivoa.xml.vospace.v2.Property; import net.ivoa.xml.vospace.v2.Property; import net.ivoa.xml.vospace.v2.Protocol; import net.ivoa.xml.vospace.v2.Protocol; import net.ivoa.xml.vospace.v2.Transfer; import net.ivoa.xml.vospace.v2.Transfer; Loading Loading @@ -439,12 +440,23 @@ public class UriServiceTest { Transfer transfer = new Transfer(); Transfer transfer = new Transfer(); transfer.setDirection("pullFromVoSpace"); transfer.setDirection("pullFromVoSpace"); transfer.setTarget(Arrays.asList("vos://example.com!vospace/file1", "vos://example.com!vospace/file2")); transfer.setTarget(Arrays.asList("vos://example.com!vospace/parent_dir")); Protocol protocol = new Protocol(); Protocol protocol = new Protocol(); protocol.setUri("ivo://ivoa.net/vospace/core#httpget"); protocol.setUri("ivo://ivoa.net/vospace/core#httpget"); transfer.getProtocols().add(protocol); transfer.getProtocols().add(protocol); View view = new View(); View view = new View(); view.setUri(viewUri); view.setUri(viewUri); Param param1 = new Param(); param1.setUri(viewUri + "/include"); param1.setValue("file1"); view.getParam().add(param1); Param param2 = new Param(); param2.setUri(viewUri + "/include"); param2.setValue("file2"); view.getParam().add(param2); transfer.setView(view); transfer.setView(view); JobSummary job = new JobSummary(); JobSummary job = new JobSummary(); Loading @@ -453,8 +465,9 @@ public class UriServiceTest { jobInfo.getAny().add(transfer); jobInfo.getAny().add(transfer); job.setJobInfo(jobInfo); job.setJobInfo(jobInfo); mockPublicNode("file1"); mockPublicNode("parent_dir"); mockPublicNode("file2"); mockPublicNode("parent_dir/file1"); mockPublicNode("parent_dir/file2"); uriService.getNegotiatedTransfer(job, transfer); uriService.getNegotiatedTransfer(job, transfer); Loading Loading
src/main/java/it/inaf/oats/vospace/FileServiceClient.java +30 −4 Original line number Original line Diff line number Diff line Loading @@ -7,6 +7,8 @@ package it.inaf.oats.vospace; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper; import it.inaf.ia2.aa.data.User; import it.inaf.ia2.aa.data.User; import it.inaf.oats.vospace.datamodel.Views; import it.inaf.oats.vospace.exception.InvalidArgumentException; import java.io.OutputStream; import java.io.OutputStream; import java.util.List; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Collectors; Loading Loading @@ -39,8 +41,32 @@ public class FileServiceClient { public String startArchiveJob(Transfer transfer, String jobId) { public String startArchiveJob(Transfer transfer, String jobId) { List<String> vosPaths = transfer.getTarget().stream() if (transfer.getTarget().size() != 1) { .map(p -> p.substring("vos://".length() + authority.length())).collect(Collectors.toList()); throw new IllegalArgumentException("Target size is " + transfer.getTarget().size()); } String target = transfer.getTarget().get(0); String viewUri = transfer.getView().getUri(); // Generate list of paths using view include parameters List<String> vosPaths = transfer.getView().getParam().stream() .map(p -> { if (p.getUri().equals(viewUri + "/include")) { if (p.getValue().contains("../")) { throw new InvalidArgumentException("Relative paths are not supported"); } return target + "/" + p.getValue(); } else { throw new InvalidArgumentException("Unsupported view parameter: " + p.getUri()); } }) .collect(Collectors.toList()); if (vosPaths.isEmpty()) { // Add target path vosPaths.add(target.substring("vos://".length() + authority.length())); } ArchiveRequest archiveRequest = new ArchiveRequest(); ArchiveRequest archiveRequest = new ArchiveRequest(); archiveRequest.setJobId(jobId); archiveRequest.setJobId(jobId); Loading Loading @@ -98,9 +124,9 @@ public class FileServiceClient { private static String archiveTypeFromViewUri(String viewUri) { private static String archiveTypeFromViewUri(String viewUri) { switch (viewUri) { switch (viewUri) { case "ivo://ia2.inaf.it/vospace/views#tar": case Views.TAR_VIEW_URI: return "TAR"; return "TAR"; case "ivo://ia2.inaf.it/vospace/views#zip": case Views.ZIP_VIEW_URI: return "ZIP"; return "ZIP"; default: default: throw new IllegalArgumentException("Archive type not defined for " + viewUri); throw new IllegalArgumentException("Archive type not defined for " + viewUri); Loading
src/test/java/it/inaf/oats/vospace/FileServiceClientTest.java +68 −1 Original line number Original line Diff line number Diff line Loading @@ -7,13 +7,16 @@ package it.inaf.oats.vospace; import it.inaf.ia2.aa.data.User; import it.inaf.ia2.aa.data.User; import it.inaf.oats.vospace.datamodel.Views; import it.inaf.oats.vospace.datamodel.Views; import it.inaf.oats.vospace.exception.InvalidArgumentException; import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream; import java.net.URI; import java.net.URI; import java.util.Arrays; import java.util.Arrays; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest; import net.ivoa.xml.vospace.v2.Param; import net.ivoa.xml.vospace.v2.Transfer; import net.ivoa.xml.vospace.v2.Transfer; import net.ivoa.xml.vospace.v2.View; import net.ivoa.xml.vospace.v2.View; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test; Loading Loading @@ -75,15 +78,79 @@ public class FileServiceClientTest { } } } } @Test public void testArchiveNoInclude() { Transfer transfer = new Transfer(); transfer.setDirection("pullFromVoSpace"); transfer.setTarget(Arrays.asList("vos://example.com!vospace/mydir")); View view = new View(); view.setUri(Views.ZIP_VIEW_URI); transfer.setView(view); testStartArchiveJob(transfer); } @Test public void testInvalidViewParam() { Transfer transfer = new Transfer(); transfer.setDirection("pullFromVoSpace"); transfer.setTarget(Arrays.asList("vos://example.com!vospace/parent_dir")); View view = new View(); view.setUri(Views.TAR_VIEW_URI); transfer.setView(view); Param param1 = new Param(); param1.setUri("invalid"); param1.setValue("file1"); view.getParam().add(param1); assertThrows(InvalidArgumentException.class, () -> testStartArchiveJob(transfer)); } @Test public void testInvalidViewParamPath() { Transfer transfer = new Transfer(); transfer.setDirection("pullFromVoSpace"); transfer.setTarget(Arrays.asList("vos://example.com!vospace/parent_dir")); View view = new View(); view.setUri(Views.TAR_VIEW_URI); transfer.setView(view); Param param1 = new Param(); param1.setUri(Views.TAR_VIEW_URI + "/include"); param1.setValue("../file1"); view.getParam().add(param1); assertThrows(InvalidArgumentException.class, () -> testStartArchiveJob(transfer)); } private void testStartArchiveJob(String viewUri) { private void testStartArchiveJob(String viewUri) { Transfer transfer = new Transfer(); Transfer transfer = new Transfer(); transfer.setDirection("pullFromVoSpace"); transfer.setDirection("pullFromVoSpace"); transfer.setTarget(Arrays.asList("vos://example.com!vospace/file1", "vos://example.com!vospace/file2")); transfer.setTarget(Arrays.asList("vos://example.com!vospace/parent_dir")); View view = new View(); View view = new View(); view.setUri(viewUri); view.setUri(viewUri); transfer.setView(view); transfer.setView(view); Param param1 = new Param(); param1.setUri(viewUri + "/include"); param1.setValue("file1"); view.getParam().add(param1); Param param2 = new Param(); param2.setUri(viewUri + "/include"); param2.setValue("file2"); view.getParam().add(param2); testStartArchiveJob(transfer); } private void testStartArchiveJob(Transfer transfer) { User user = mock(User.class); User user = mock(User.class); when(user.getAccessToken()).thenReturn("<token>"); when(user.getAccessToken()).thenReturn("<token>"); when(request.getUserPrincipal()).thenReturn(user); when(request.getUserPrincipal()).thenReturn(user); Loading
src/test/java/it/inaf/oats/vospace/UriServiceTest.java +22 −9 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ import net.ivoa.xml.uws.v1.JobSummary; import net.ivoa.xml.vospace.v2.ContainerNode; import net.ivoa.xml.vospace.v2.ContainerNode; import net.ivoa.xml.vospace.v2.DataNode; import net.ivoa.xml.vospace.v2.DataNode; import net.ivoa.xml.vospace.v2.Node; import net.ivoa.xml.vospace.v2.Node; import net.ivoa.xml.vospace.v2.Param; import net.ivoa.xml.vospace.v2.Property; import net.ivoa.xml.vospace.v2.Property; import net.ivoa.xml.vospace.v2.Protocol; import net.ivoa.xml.vospace.v2.Protocol; import net.ivoa.xml.vospace.v2.Transfer; import net.ivoa.xml.vospace.v2.Transfer; Loading Loading @@ -439,12 +440,23 @@ public class UriServiceTest { Transfer transfer = new Transfer(); Transfer transfer = new Transfer(); transfer.setDirection("pullFromVoSpace"); transfer.setDirection("pullFromVoSpace"); transfer.setTarget(Arrays.asList("vos://example.com!vospace/file1", "vos://example.com!vospace/file2")); transfer.setTarget(Arrays.asList("vos://example.com!vospace/parent_dir")); Protocol protocol = new Protocol(); Protocol protocol = new Protocol(); protocol.setUri("ivo://ivoa.net/vospace/core#httpget"); protocol.setUri("ivo://ivoa.net/vospace/core#httpget"); transfer.getProtocols().add(protocol); transfer.getProtocols().add(protocol); View view = new View(); View view = new View(); view.setUri(viewUri); view.setUri(viewUri); Param param1 = new Param(); param1.setUri(viewUri + "/include"); param1.setValue("file1"); view.getParam().add(param1); Param param2 = new Param(); param2.setUri(viewUri + "/include"); param2.setValue("file2"); view.getParam().add(param2); transfer.setView(view); transfer.setView(view); JobSummary job = new JobSummary(); JobSummary job = new JobSummary(); Loading @@ -453,8 +465,9 @@ public class UriServiceTest { jobInfo.getAny().add(transfer); jobInfo.getAny().add(transfer); job.setJobInfo(jobInfo); job.setJobInfo(jobInfo); mockPublicNode("file1"); mockPublicNode("parent_dir"); mockPublicNode("file2"); mockPublicNode("parent_dir/file1"); mockPublicNode("parent_dir/file2"); uriService.getNegotiatedTransfer(job, transfer); uriService.getNegotiatedTransfer(job, transfer); Loading