Loading vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/client/VOSpaceClient.java +24 −9 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ import it.inaf.ia2.vospace.ui.data.Job; import it.inaf.ia2.vospace.ui.exception.BadRequestException; import it.inaf.ia2.vospace.ui.exception.VOSpaceStatusException; import it.inaf.ia2.vospace.ui.exception.VOSpaceException; import it.inaf.oats.vospace.datamodel.NodeUtils; import static it.inaf.oats.vospace.datamodel.NodeUtils.urlEncodePath; import java.io.IOException; import java.io.InputStream; Loading @@ -25,6 +26,7 @@ import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Scanner; import java.util.concurrent.CompletionException; import java.util.concurrent.ForkJoinPool; Loading Loading @@ -56,9 +58,6 @@ public class VOSpaceClient { @Value("${use-json}") private boolean useJson; @Value("${vospace-authority}") private String authority; private static final ObjectMapper MAPPER = new ObjectMapper(); private final HttpClient httpClient; Loading @@ -84,8 +83,12 @@ public class VOSpaceClient { } public Node getNode(String path) { return getNode(path, Optional.empty()); } HttpRequest request = getRequest("/nodes" + urlEncodePath(path)) public Node getNode(String path, Optional<String> adminToken) { HttpRequest request = getRequest("/nodes" + urlEncodePath(path), adminToken) .header("Accept", useJson ? "application/json" : "text/xml") .build(); Loading Loading @@ -140,10 +143,14 @@ public class VOSpaceClient { } public Node createNode(Node node) { return createNode(node, Optional.empty()); } String path = node.getUri().substring(("vos://" + authority).length()); public Node createNode(Node node, Optional<String> adminToken) { HttpRequest request = getRequest("/nodes" + path) String path = NodeUtils.getVosPath(node); HttpRequest request = getRequest("/nodes" + urlEncodePath(path), adminToken) .header("Accept", useJson ? "application/json" : "text/xml") .header("Content-Type", useJson ? "application/json" : "text/xml") .PUT(HttpRequest.BodyPublishers.ofString(marshal(node))) Loading @@ -164,10 +171,14 @@ public class VOSpaceClient { } public Node setNode(Node node, boolean recursive) { return setNode(node, recursive, Optional.empty()); } public Node setNode(Node node, boolean recursive, Optional<String> adminToken) { String path = node.getUri().substring(("vos://" + authority).length()); String path = NodeUtils.getVosPath(node); HttpRequest request = getRequest("/nodes" + urlEncodePath(path) + "?recursive=" + recursive) HttpRequest request = getRequest("/nodes" + urlEncodePath(path) + "?recursive=" + recursive, adminToken) .header("Accept", useJson ? "application/json" : "text/xml") .header("Content-Type", useJson ? "application/json" : "text/xml") .POST(HttpRequest.BodyPublishers.ofString(marshal(node))) Loading Loading @@ -281,8 +292,12 @@ public class VOSpaceClient { } private HttpRequest.Builder getRequest(String path) { return getRequest(path, Optional.empty()); } private HttpRequest.Builder getRequest(String path, Optional<String> adminToken) { HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create(baseUrl + path)); String token = getToken(); String token = adminToken.orElseGet(() -> getToken()); if (token != null) { builder.setHeader("Authorization", "Bearer " + token); } Loading vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/NodesController.java +17 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,9 @@ import it.inaf.ia2.vospace.ui.service.MainNodesHtmlGenerator; import it.inaf.ia2.vospace.ui.service.MoveOrCopyNodeModalHtmlGenerator; import it.inaf.oats.vospace.datamodel.NodeUtils; import static it.inaf.oats.vospace.datamodel.NodeUtils.urlEncodePath; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Map; Loading @@ -43,6 +46,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; Loading Loading @@ -132,7 +136,9 @@ public class NodesController extends BaseController { for (LinkNode linkNode : linksToLoad) { String prefix = "vos://" + authority; if (linkNode.getTarget().startsWith(prefix)) { String linkPath = linkNode.getTarget().substring(prefix.length()); String linkPath = StringUtils.uriDecode(linkNode.getTarget(), StandardCharsets.UTF_8) .substring(prefix.length()); nodesCalls.add(CompletableFuture.supplyAsync(() -> client.getNode(linkPath), Runnable::run) .exceptionally(ex -> null)); // null is returned in case of broken link } else { Loading Loading @@ -225,10 +231,10 @@ public class NodesController extends BaseController { transfer.setView(view); if (paths.size() == 1) { transfer.setTarget("vos://" + authority + paths.get(0)); transfer.setTarget(getUri(paths.get(0))); } else { String parent = getCommonParent(paths); transfer.setTarget("vos://" + authority + parent); transfer.setTarget(getUri(parent)); for (String path : paths) { String childName = path.substring(parent.length() + 1); Param param = new Param(); Loading @@ -246,6 +252,14 @@ public class NodesController extends BaseController { return new Job(client.startTransferJob(transfer), Job.JobType.ARCHIVE); } private String getUri(String path) { try { return new URI("vos", authority, path, null, null).toASCIIString(); } catch (URISyntaxException ex) { throw new RuntimeException(ex); } } private String getCommonParent(List<String> vosPaths) { String commonParent = null; for (String vosPath : vosPaths) { Loading vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/data/ShareRequest.java +9 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ public class ShareRequest { private List<String> userRead; private List<String> userWrite; private boolean recursive; private List<String> newPeople; public String getPath() { return path; Loading Loading @@ -63,4 +64,12 @@ public class ShareRequest { public void setRecursive(boolean recursive) { this.recursive = recursive; } public List<String> getNewPeople() { return newPeople; } public void setNewPeople(List<String> newPeople) { this.newPeople = newPeople; } } vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/MainNodesHtmlGenerator.java +14 −5 Original line number Diff line number Diff line Loading @@ -173,6 +173,10 @@ public class MainNodesHtmlGenerator extends NodesHtmlGenerator { } private boolean isDownloadable(NodeInfo nodeInfo, User user) { if (nodeInfo.isBrokenLink()) { return false; } if (nodeInfo.isFile()) { if (nodeInfo.isAsyncTrans() || nodeInfo.isBusy()) { return false; Loading @@ -186,7 +190,11 @@ public class MainNodesHtmlGenerator extends NodesHtmlGenerator { return true; } if (user.getGroups() != null && !user.getGroups().isEmpty() && !nodeInfo.getGroupRead().isEmpty()) { if (user.getGroups() != null) { if (user.getGroups().contains("VOSpace.ADMIN")) { return true; } if (!user.getGroups().isEmpty() && !nodeInfo.getGroupRead().isEmpty()) { List<String> groupRead = Arrays.asList(nodeInfo.getGroupRead().split(" ")); for (String group : groupRead) { if (user.getGroups().contains(group)) { Loading @@ -194,6 +202,7 @@ public class MainNodesHtmlGenerator extends NodesHtmlGenerator { } } } } return false; } Loading vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/NodeInfo.java +10 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ public class NodeInfo { private final String path; private final String name; private final String size; private boolean brokenLink; private String type; private final String creator; private final String groupRead; Loading Loading @@ -63,7 +64,11 @@ public class NodeInfo { this.type = linkedNode.getType(); } else if (node instanceof LinkNode) { this.target = ((LinkNode) node).getTarget(); this.type = "vos:DataNode"; // data link if (this.target.startsWith("vos://" + authority)) { this.brokenLink = true; } else { this.type = "vos:DataNode"; // external data link } } } Loading Loading @@ -215,4 +220,8 @@ public class NodeInfo { public boolean isLink() { return target != null; } public boolean isBrokenLink() { return brokenLink; } } Loading
vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/client/VOSpaceClient.java +24 −9 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ import it.inaf.ia2.vospace.ui.data.Job; import it.inaf.ia2.vospace.ui.exception.BadRequestException; import it.inaf.ia2.vospace.ui.exception.VOSpaceStatusException; import it.inaf.ia2.vospace.ui.exception.VOSpaceException; import it.inaf.oats.vospace.datamodel.NodeUtils; import static it.inaf.oats.vospace.datamodel.NodeUtils.urlEncodePath; import java.io.IOException; import java.io.InputStream; Loading @@ -25,6 +26,7 @@ import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Scanner; import java.util.concurrent.CompletionException; import java.util.concurrent.ForkJoinPool; Loading Loading @@ -56,9 +58,6 @@ public class VOSpaceClient { @Value("${use-json}") private boolean useJson; @Value("${vospace-authority}") private String authority; private static final ObjectMapper MAPPER = new ObjectMapper(); private final HttpClient httpClient; Loading @@ -84,8 +83,12 @@ public class VOSpaceClient { } public Node getNode(String path) { return getNode(path, Optional.empty()); } HttpRequest request = getRequest("/nodes" + urlEncodePath(path)) public Node getNode(String path, Optional<String> adminToken) { HttpRequest request = getRequest("/nodes" + urlEncodePath(path), adminToken) .header("Accept", useJson ? "application/json" : "text/xml") .build(); Loading Loading @@ -140,10 +143,14 @@ public class VOSpaceClient { } public Node createNode(Node node) { return createNode(node, Optional.empty()); } String path = node.getUri().substring(("vos://" + authority).length()); public Node createNode(Node node, Optional<String> adminToken) { HttpRequest request = getRequest("/nodes" + path) String path = NodeUtils.getVosPath(node); HttpRequest request = getRequest("/nodes" + urlEncodePath(path), adminToken) .header("Accept", useJson ? "application/json" : "text/xml") .header("Content-Type", useJson ? "application/json" : "text/xml") .PUT(HttpRequest.BodyPublishers.ofString(marshal(node))) Loading @@ -164,10 +171,14 @@ public class VOSpaceClient { } public Node setNode(Node node, boolean recursive) { return setNode(node, recursive, Optional.empty()); } public Node setNode(Node node, boolean recursive, Optional<String> adminToken) { String path = node.getUri().substring(("vos://" + authority).length()); String path = NodeUtils.getVosPath(node); HttpRequest request = getRequest("/nodes" + urlEncodePath(path) + "?recursive=" + recursive) HttpRequest request = getRequest("/nodes" + urlEncodePath(path) + "?recursive=" + recursive, adminToken) .header("Accept", useJson ? "application/json" : "text/xml") .header("Content-Type", useJson ? "application/json" : "text/xml") .POST(HttpRequest.BodyPublishers.ofString(marshal(node))) Loading Loading @@ -281,8 +292,12 @@ public class VOSpaceClient { } private HttpRequest.Builder getRequest(String path) { return getRequest(path, Optional.empty()); } private HttpRequest.Builder getRequest(String path, Optional<String> adminToken) { HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create(baseUrl + path)); String token = getToken(); String token = adminToken.orElseGet(() -> getToken()); if (token != null) { builder.setHeader("Authorization", "Bearer " + token); } Loading
vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/NodesController.java +17 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,9 @@ import it.inaf.ia2.vospace.ui.service.MainNodesHtmlGenerator; import it.inaf.ia2.vospace.ui.service.MoveOrCopyNodeModalHtmlGenerator; import it.inaf.oats.vospace.datamodel.NodeUtils; import static it.inaf.oats.vospace.datamodel.NodeUtils.urlEncodePath; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Map; Loading @@ -43,6 +46,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; Loading Loading @@ -132,7 +136,9 @@ public class NodesController extends BaseController { for (LinkNode linkNode : linksToLoad) { String prefix = "vos://" + authority; if (linkNode.getTarget().startsWith(prefix)) { String linkPath = linkNode.getTarget().substring(prefix.length()); String linkPath = StringUtils.uriDecode(linkNode.getTarget(), StandardCharsets.UTF_8) .substring(prefix.length()); nodesCalls.add(CompletableFuture.supplyAsync(() -> client.getNode(linkPath), Runnable::run) .exceptionally(ex -> null)); // null is returned in case of broken link } else { Loading Loading @@ -225,10 +231,10 @@ public class NodesController extends BaseController { transfer.setView(view); if (paths.size() == 1) { transfer.setTarget("vos://" + authority + paths.get(0)); transfer.setTarget(getUri(paths.get(0))); } else { String parent = getCommonParent(paths); transfer.setTarget("vos://" + authority + parent); transfer.setTarget(getUri(parent)); for (String path : paths) { String childName = path.substring(parent.length() + 1); Param param = new Param(); Loading @@ -246,6 +252,14 @@ public class NodesController extends BaseController { return new Job(client.startTransferJob(transfer), Job.JobType.ARCHIVE); } private String getUri(String path) { try { return new URI("vos", authority, path, null, null).toASCIIString(); } catch (URISyntaxException ex) { throw new RuntimeException(ex); } } private String getCommonParent(List<String> vosPaths) { String commonParent = null; for (String vosPath : vosPaths) { Loading
vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/data/ShareRequest.java +9 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ public class ShareRequest { private List<String> userRead; private List<String> userWrite; private boolean recursive; private List<String> newPeople; public String getPath() { return path; Loading Loading @@ -63,4 +64,12 @@ public class ShareRequest { public void setRecursive(boolean recursive) { this.recursive = recursive; } public List<String> getNewPeople() { return newPeople; } public void setNewPeople(List<String> newPeople) { this.newPeople = newPeople; } }
vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/MainNodesHtmlGenerator.java +14 −5 Original line number Diff line number Diff line Loading @@ -173,6 +173,10 @@ public class MainNodesHtmlGenerator extends NodesHtmlGenerator { } private boolean isDownloadable(NodeInfo nodeInfo, User user) { if (nodeInfo.isBrokenLink()) { return false; } if (nodeInfo.isFile()) { if (nodeInfo.isAsyncTrans() || nodeInfo.isBusy()) { return false; Loading @@ -186,7 +190,11 @@ public class MainNodesHtmlGenerator extends NodesHtmlGenerator { return true; } if (user.getGroups() != null && !user.getGroups().isEmpty() && !nodeInfo.getGroupRead().isEmpty()) { if (user.getGroups() != null) { if (user.getGroups().contains("VOSpace.ADMIN")) { return true; } if (!user.getGroups().isEmpty() && !nodeInfo.getGroupRead().isEmpty()) { List<String> groupRead = Arrays.asList(nodeInfo.getGroupRead().split(" ")); for (String group : groupRead) { if (user.getGroups().contains(group)) { Loading @@ -194,6 +202,7 @@ public class MainNodesHtmlGenerator extends NodesHtmlGenerator { } } } } return false; } Loading
vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/NodeInfo.java +10 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ public class NodeInfo { private final String path; private final String name; private final String size; private boolean brokenLink; private String type; private final String creator; private final String groupRead; Loading Loading @@ -63,7 +64,11 @@ public class NodeInfo { this.type = linkedNode.getType(); } else if (node instanceof LinkNode) { this.target = ((LinkNode) node).getTarget(); this.type = "vos:DataNode"; // data link if (this.target.startsWith("vos://" + authority)) { this.brokenLink = true; } else { this.type = "vos:DataNode"; // external data link } } } Loading Loading @@ -215,4 +220,8 @@ public class NodeInfo { public boolean isLink() { return target != null; } public boolean isBrokenLink() { return brokenLink; } }