madisonmlin commented on code in PR #3728:
URL: https://github.com/apache/texera/pull/3728#discussion_r2404884920
##########
core/amber/src/main/scala/edu/uci/ics/texera/web/resource/dashboard/user/workflow/WorkflowExecutionsResource.scala:
##########
@@ -688,76 +691,53 @@ class WorkflowExecutionsResource {
}
@POST
- @Path("/result/export")
+ @Path("/result/export/dataset")
@RolesAllowed(Array("REGULAR", "ADMIN"))
- def exportResult(
- request: ResultExportRequest,
- @Auth user: SessionUser
- ): Response = {
-
- if (request.operators.size <= 0)
- Response
- .status(Response.Status.BAD_REQUEST)
- .`type`(MediaType.APPLICATION_JSON)
- .entity(Map("error" -> "No operator selected").asJava)
- .build()
-
+ def exportResult(request: ResultExportRequest, @Auth user: SessionUser):
Response = {
try {
- request.destination match {
- case "local" =>
- // CASE A: multiple operators => produce ZIP
- if (request.operators.size > 1) {
- val resultExportService =
- new ResultExportService(WorkflowIdentity(request.workflowId),
request.computingUnitId)
- val (zipStream, zipFileNameOpt) =
- resultExportService.exportOperatorsAsZip(request)
-
- if (zipStream == null) {
- throw new RuntimeException("Zip stream is null")
- }
+ val resultExportService =
+ new ResultExportService(WorkflowIdentity(request.workflowId),
request.computingUnitId)
+ resultExportService.validateExportRequest(request) match {
+ case Some(errorResponse) => errorResponse
+ case None =>
resultExportService.exportToDataset(user.user, request)
+ }
+ } catch {
+ case ex: Exception =>
+ Response
+ .status(Response.Status.INTERNAL_SERVER_ERROR)
+ .`type`(MediaType.APPLICATION_JSON)
+ .entity(Map("error" -> ex.getMessage).asJava)
+ .build()
+ }
+ }
- val finalFileName = zipFileNameOpt.getOrElse("operators.zip")
- return Response
- .ok(zipStream, "application/zip")
- .header("Content-Disposition", "attachment; filename=\"" +
finalFileName + "\"")
- .build()
- }
+ @POST
+ @Path("/result/export/local")
+ @Consumes(Array(MediaType.APPLICATION_FORM_URLENCODED))
+ def exportResultViaBrowser(
+ @FormParam("request") requestJson: String,
+ @FormParam("token") token: String
+ ): Response = {
- // CASE B: exactly one operator => single file
- if (request.operators.size != 1) {
- return Response
- .status(Response.Status.BAD_REQUEST)
- .`type`(MediaType.APPLICATION_JSON)
- .entity(Map("error" -> "Local download does not support no
operator.").asJava)
- .build()
- }
- val singleOp = request.operators.head
-
- val resultExportService =
- new ResultExportService(WorkflowIdentity(request.workflowId),
request.computingUnitId)
- val (streamingOutput, fileNameOpt) =
- resultExportService.exportOperatorResultAsStream(request, singleOp)
-
- if (streamingOutput == null) {
- return Response
- .status(Response.Status.INTERNAL_SERVER_ERROR)
- .`type`(MediaType.APPLICATION_JSON)
- .entity(Map("error" -> "Failed to export operator").asJava)
- .build()
- }
+ try {
+ val userOpt = JwtParser.parseToken(token)
+ if (userOpt.isPresent) {
+ val user = userOpt.get()
+ val role = user.getUser.getRole
+ val RolesAllowed = Set(UserRoleEnum.REGULAR, UserRoleEnum.ADMIN)
+ if (!RolesAllowed.contains(role)) {
+ throw new RuntimeException("User role is not allowed to perform this
download")
+ }
+ } else {
+ throw new RuntimeException("Invalid or expired token")
+ }
- val finalFileName = fileNameOpt.getOrElse("download.dat")
- Response
- .ok(streamingOutput, MediaType.APPLICATION_OCTET_STREAM)
- .header("Content-Disposition", "attachment; filename=\"" +
finalFileName + "\"")
- .build()
- case _ =>
- // destination = "dataset" by default
- val resultExportService =
- new ResultExportService(WorkflowIdentity(request.workflowId),
request.computingUnitId)
- val exportResponse =
- resultExportService.exportAllOperatorsResultToDataset(user.user,
request)
- Response.ok(exportResponse).build()
+ val request = Json.parse(requestJson).as[ResultExportRequest]
+ val resultExportService =
Review Comment:
I haven't merged them, since they call different methods `exportToLocal` and
`exportToDataset`, but I've removed the validation method so hopefully it's a
bit easier to read now.
Do you think it's generally better to check for invalid inputs (like empty
operators list) in the frontend or backend?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]