diff --git a/pic-sure-api-data/pom.xml b/pic-sure-api-data/pom.xml index beed91bd..b4a89706 100755 --- a/pic-sure-api-data/pom.xml +++ b/pic-sure-api-data/pom.xml @@ -6,7 +6,7 @@ edu.harvard.hms.dbmi.avillach pic-sure-api - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT pic-sure-api-data pic-sure-api-data diff --git a/pic-sure-api-war/pom.xml b/pic-sure-api-war/pom.xml index 9d476c96..f694c488 100755 --- a/pic-sure-api-war/pom.xml +++ b/pic-sure-api-war/pom.xml @@ -6,7 +6,7 @@ edu.harvard.hms.dbmi.avillach pic-sure-api - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT pic-sure-api-war PIC-SURE API war diff --git a/pic-sure-api-war/src/main/java/edu/harvard/dbmi/avillach/PicsureRS.java b/pic-sure-api-war/src/main/java/edu/harvard/dbmi/avillach/PicsureRS.java index 9eb58a36..2f711dcf 100644 --- a/pic-sure-api-war/src/main/java/edu/harvard/dbmi/avillach/PicsureRS.java +++ b/pic-sure-api-war/src/main/java/edu/harvard/dbmi/avillach/PicsureRS.java @@ -154,20 +154,37 @@ public QueryStatus queryStatus( @POST @Path("/query/{queryId}/result") @Operation( - summary = "Returns result for given query", - responses = {@ApiResponse( - responseCode = "200", description = "Query result", content = @Content(schema = @Schema(implementation = Response.class)) - )} + summary = "Returns result for given query", + responses = {@ApiResponse( + responseCode = "200", description = "Query result", content = @Content(schema = @Schema(implementation = Response.class)) + )} ) @Produces(MediaType.APPLICATION_OCTET_STREAM) public Response queryResult( - @Parameter( - description = "The UUID of the query to fetch the status of. The UUID is " - + "returned by the /query endpoint as the \"picsureResultId\" in the response object" - ) @PathParam("queryId") UUID queryId, @Parameter QueryRequest credentialsQueryRequest, @Context HttpHeaders headers + @Parameter( + description = "The UUID of the query to fetch the status of. The UUID is " + + "returned by the /query endpoint as the \"picsureResultId\" in the response object" + ) @PathParam("queryId") UUID queryId, @Parameter QueryRequest credentialsQueryRequest, @Context HttpHeaders headers ) { return queryService.queryResult(queryId, credentialsQueryRequest, headers); } + @POST + @Path("/query/{queryId}/signed-url") + @Operation( + summary = "Returns a signed url for given query", + responses = {@ApiResponse( + responseCode = "200", description = "Query result", content = @Content(schema = @Schema(implementation = Response.class)) + )} + ) + @Produces(MediaType.APPLICATION_JSON) + public Response queryResultSignedUrl( + @Parameter( + description = "The UUID of the query to fetch the status of. The UUID is " + + "returned by the /query endpoint as the \"picsureResultId\" in the response object" + ) @PathParam("queryId") UUID queryId, @Parameter QueryRequest credentialsQueryRequest, @Context HttpHeaders headers + ) { + return queryService.queryResultSignedUrl(queryId, credentialsQueryRequest, headers); + } @POST @Path("/query/sync") diff --git a/pic-sure-api-war/src/main/java/edu/harvard/dbmi/avillach/service/PicsureQueryService.java b/pic-sure-api-war/src/main/java/edu/harvard/dbmi/avillach/service/PicsureQueryService.java index ca93d6d8..74945080 100644 --- a/pic-sure-api-war/src/main/java/edu/harvard/dbmi/avillach/service/PicsureQueryService.java +++ b/pic-sure-api-war/src/main/java/edu/harvard/dbmi/avillach/service/PicsureQueryService.java @@ -149,8 +149,8 @@ public Response queryResult(UUID queryId, QueryRequest credentialsQueryRequest, } logger.info( - "path=/query/{queryId}/result, resourceId={}, requestSource={}, queryRequest={}", queryId, - Utilities.getRequestSourceFromHeader(headers), Utilities.convertQueryRequestToString(mapper, credentialsQueryRequest) + "path=/query/{queryId}/result, resourceId={}, requestSource={}, queryRequest={}", queryId, + Utilities.getRequestSourceFromHeader(headers), Utilities.convertQueryRequestToString(mapper, credentialsQueryRequest) ); @@ -158,6 +158,46 @@ public Response queryResult(UUID queryId, QueryRequest credentialsQueryRequest, return resourceWebClient.queryResult(resource.getResourceRSPath(), query.getResourceResultId(), credentialsQueryRequest); } + /** + * Returns a signed URL from HPDS that is a reference to the query result + * + * @param queryId - id of target resource + * @param credentialsQueryRequest - contains resource specific credentials object + * @return Response containing a signed URL + */ + @Transactional + public Response queryResultSignedUrl(UUID queryId, QueryRequest credentialsQueryRequest, HttpHeaders headers) { + if (queryId == null) { + throw new ProtocolException(ProtocolException.MISSING_QUERY_ID); + } + Query query = queryRepo.getById(queryId); + if (query == null) { + throw new ProtocolException(ProtocolException.QUERY_NOT_FOUND + queryId.toString()); + } + Resource resource = query.getResource(); + if (resource == null) { + throw new ApplicationException(ApplicationException.MISSING_RESOURCE); + } + if (resource.getResourceRSPath() == null) { + throw new ApplicationException(ApplicationException.MISSING_RESOURCE_PATH); + } + if (credentialsQueryRequest == null) { + throw new ProtocolException(ProtocolException.MISSING_DATA); + } + if (credentialsQueryRequest.getResourceCredentials() == null) { + credentialsQueryRequest.setResourceCredentials(new HashMap<>()); + } + + logger.info( + "path=/query/{queryId}/signed-url, resourceId={}, requestSource={}, queryRequest={}", queryId, + Utilities.getRequestSourceFromHeader(headers), Utilities.convertQueryRequestToString(mapper, credentialsQueryRequest) + ); + + + credentialsQueryRequest.getResourceCredentials().put(ResourceWebClient.BEARER_TOKEN_KEY, resource.getToken()); + return resourceWebClient.queryResultSignedUrl(resource.getResourceRSPath(), query.getResourceResultId(), credentialsQueryRequest); + } + /** * Streams the result for a query by looking up the target resource from the database and calling the target resource for a result. * diff --git a/pic-sure-resources/pic-sure-aggregate-data-sharing-resource/pom.xml b/pic-sure-resources/pic-sure-aggregate-data-sharing-resource/pom.xml index 47ac0ff4..161e48cb 100644 --- a/pic-sure-resources/pic-sure-aggregate-data-sharing-resource/pom.xml +++ b/pic-sure-resources/pic-sure-aggregate-data-sharing-resource/pom.xml @@ -6,7 +6,7 @@ edu.harvard.hms.dbmi.avillach pic-sure-resources - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT pic-sure-aggregate-data-sharing-resource pic-sure-aggregate-data-sharing-resource diff --git a/pic-sure-resources/pic-sure-ga4gh-dos/pom.xml b/pic-sure-resources/pic-sure-ga4gh-dos/pom.xml index 2bc99fa9..8f750d9f 100644 --- a/pic-sure-resources/pic-sure-ga4gh-dos/pom.xml +++ b/pic-sure-resources/pic-sure-ga4gh-dos/pom.xml @@ -6,7 +6,7 @@ edu.harvard.hms.dbmi.avillach pic-sure-resources - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT pic-sure-ga4gh-dos pic-sure-ga4gh-dos diff --git a/pic-sure-resources/pic-sure-passthrough-resource/pom.xml b/pic-sure-resources/pic-sure-passthrough-resource/pom.xml index e4eec756..6597de44 100644 --- a/pic-sure-resources/pic-sure-passthrough-resource/pom.xml +++ b/pic-sure-resources/pic-sure-passthrough-resource/pom.xml @@ -5,7 +5,7 @@ edu.harvard.hms.dbmi.avillach pic-sure-resources - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT pic-sure-passthrough-resource pic-sure-passthrough-resource diff --git a/pic-sure-resources/pic-sure-resource-api/pom.xml b/pic-sure-resources/pic-sure-resource-api/pom.xml index cae79567..2d15aaa9 100755 --- a/pic-sure-resources/pic-sure-resource-api/pom.xml +++ b/pic-sure-resources/pic-sure-resource-api/pom.xml @@ -5,7 +5,7 @@ edu.harvard.hms.dbmi.avillach pic-sure-resources - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT pic-sure-resource-api pic-sure-resource-api diff --git a/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/domain/SignedUrlResponse.java b/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/domain/SignedUrlResponse.java new file mode 100644 index 00000000..265f73ab --- /dev/null +++ b/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/domain/SignedUrlResponse.java @@ -0,0 +1,33 @@ +package edu.harvard.dbmi.avillach.domain; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +public class SignedUrlResponse { + + private final String signedUrl; + + @JsonCreator + public SignedUrlResponse(@JsonProperty("signedUrl") String signedUrl) { + this.signedUrl = signedUrl; + } + + public String getSignedUrl() { + return signedUrl; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SignedUrlResponse that = (SignedUrlResponse) o; + return Objects.equals(signedUrl, that.signedUrl); + } + + @Override + public int hashCode() { + return Objects.hash(signedUrl); + } +} diff --git a/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/ResourceWebClient.java b/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/ResourceWebClient.java index 211cf239..09567c41 100644 --- a/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/ResourceWebClient.java +++ b/pic-sure-resources/pic-sure-resource-api/src/main/java/edu/harvard/dbmi/avillach/service/ResourceWebClient.java @@ -211,6 +211,37 @@ public Response queryResult(String rsURL, String queryId, QueryRequest queryRequ throw new ResourceInterfaceException("Error getting results", e); } } + + public Response queryResultSignedUrl(String rsURL, String queryId, QueryRequest queryRequest){ + logger.debug("Calling ResourceWebClient querySignedUrl()"); + try { + if (queryRequest == null){ + throw new ProtocolException(ProtocolException.MISSING_DATA); + } + if (queryRequest.getResourceCredentials() == null){ + throw new NotAuthorizedException("Missing credentials"); + } + if (rsURL == null){ + throw new ApplicationException(ApplicationException.MISSING_RESOURCE_PATH); + } + if (queryId == null){ + throw new ProtocolException(ProtocolException.MISSING_QUERY_ID); + } + String pathName = "/query/" + queryId + "/signed-url"; + String body = json.writeValueAsString(queryRequest); + HttpResponse resourcesResponse = retrievePostResponse(composeURL(rsURL, pathName), createHeaders(queryRequest.getResourceCredentials()), body); + if (resourcesResponse.getStatusLine().getStatusCode() != 200) { + logger.error("ResourceRS did not return a 200"); + throwResponseError(resourcesResponse, rsURL); + } + return Response.ok(resourcesResponse.getEntity().getContent()).build(); + } catch (JsonProcessingException e){ + logger.error("Unable to encode resource credentials"); + throw new NotAuthorizedException("Unable to encode resource credentials", e); + } catch (IOException e){ + throw new ResourceInterfaceException("Error getting results", e); + } + } public Response queryFormat(String rsURL, QueryRequest queryRequest){ diff --git a/pic-sure-resources/pic-sure-resource-api/src/test/java/edu/harvard/dbmi/avillach/domain/SignedUrlResponseTest.java b/pic-sure-resources/pic-sure-resource-api/src/test/java/edu/harvard/dbmi/avillach/domain/SignedUrlResponseTest.java new file mode 100644 index 00000000..14f9d128 --- /dev/null +++ b/pic-sure-resources/pic-sure-resource-api/src/test/java/edu/harvard/dbmi/avillach/domain/SignedUrlResponseTest.java @@ -0,0 +1,18 @@ +package edu.harvard.dbmi.avillach.domain; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; +import static org.junit.Assert.*; + +public class SignedUrlResponseTest { + + @Test + public void testJacksonSerialization() throws JsonProcessingException { + SignedUrlResponse signedUrlResponse = new SignedUrlResponse("http://google.com/"); + ObjectMapper objectMapper = new ObjectMapper(); + String serialized = objectMapper.writeValueAsString(signedUrlResponse); + SignedUrlResponse deserialized = objectMapper.readValue(serialized, SignedUrlResponse.class); + assertEquals(signedUrlResponse.getSignedUrl(), deserialized.getSignedUrl()); + } +} diff --git a/pic-sure-resources/pic-sure-visualization-resource/pom.xml b/pic-sure-resources/pic-sure-visualization-resource/pom.xml index 164e002f..c118a5e7 100644 --- a/pic-sure-resources/pic-sure-visualization-resource/pom.xml +++ b/pic-sure-resources/pic-sure-visualization-resource/pom.xml @@ -5,7 +5,7 @@ edu.harvard.hms.dbmi.avillach pic-sure-resources - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT pic-sure-visualization-resource PIC-SURE Visualization Resource diff --git a/pic-sure-resources/pom.xml b/pic-sure-resources/pom.xml index f6c59db2..2cf49817 100644 --- a/pic-sure-resources/pom.xml +++ b/pic-sure-resources/pom.xml @@ -4,7 +4,7 @@ pic-sure-api edu.harvard.hms.dbmi.avillach - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT pic-sure-resources pom diff --git a/pic-sure-util/pom.xml b/pic-sure-util/pom.xml index 22470efb..4806886d 100644 --- a/pic-sure-util/pom.xml +++ b/pic-sure-util/pom.xml @@ -5,7 +5,7 @@ pic-sure-api edu.harvard.hms.dbmi.avillach - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT 4.0.0 pic-sure-util diff --git a/pom.xml b/pom.xml index e46782a2..bce8d568 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 edu.harvard.hms.dbmi.avillach pic-sure-api - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT pom pic-sure-api