aicam opened a new pull request, #7994:
URL: https://github.com/apache/texera/pull/7994
### What changes were proposed in this PR?
The two result-export endpoints build their work entirely out of the request
body — `workflowId`, `computingUnitId`, and the operator list — and the only
thing either of them checks today is that the caller has read access to the
workflow.
Two rules that the export dialog applies in the browser never reach the
server:
- `GET /executions/{wid}/result/downloadability` computes, per operator,
which datasets marked `is_downloadable = false` feed it, propagated downstream
through the workflow graph. The dialog greys those operators out. Neither
export endpoint consults the same map, so the restriction holds only for as
long as the client cooperates.
- The dialog can only name the computing unit the workspace is attached to,
but `getLatestExecutionID` selects on `(wid, cuid)` alone, so the unit id is
otherwise just another body field.
So the same request is answered differently depending on which client sends
it, and the dataset owner's downloadability setting is enforced in exactly one
of the two places that act on it.
Both endpoints now share one `validateUserCanExportResult`, which keeps the
existing workflow read-access check and adds the two missing rules:
1. read access to the workflow (unchanged);
2. read access to the computing unit named in the request, through
`ComputingUnitAccess.getComputingUnitAccess` — a unit shared with the caller
still exports, an unrelated one does not;
3. no requested operator carries data out of a non-downloadable dataset the
caller does not own, using the same map the downloadability endpoint already
returns to the UI.
The two new refusals answer `403` rather than the `401` the workflow check
returns. The caller's session is valid in both new cases, and the frontend's
`UnauthorizedHttpInterceptor` treats any `401` on an authenticated request as
an expired session and logs the user out — the wrong outcome for a live session
that merely asked for something it is not entitled to.
### Any related issues, documentation, discussions?
No issue. The per-operator restriction map and the dialog that consumes it
already exist; this PR only makes the endpoints behind the dialog apply the
same rule.
### How was this PR tested?
`WorkflowExecutionsResourceSpec`, six new cases covering both endpoints:
| Case | What it pins |
|---|---|
| computing unit the caller cannot reach (local + dataset) | `403` and the
message, for a unit owned by another user |
| computing unit shared with the caller | a unit someone else owns but
granted the caller `READ` on still exports — the predicate is access, not
ownership |
| operator fed by a non-downloadable dataset (local + dataset) | `403`
naming the blocking dataset; the local case asks for the *downstream* operator,
so the restriction's propagation along the links is covered too |
| unrestricted operator of a restricted workflow | one restriction in a
workflow does not close down the whole workflow |
Two existing cases named computing unit `0`, which no unit can have; they
now insert a real unit so they still reach the code they were written for.
```
STORAGE_ICEBERG_CATALOG_TYPE=postgres sbt "WorkflowExecutionService/testOnly
org.apache.texera.web.resource.dashboard.user.workflow.WorkflowExecutionsResourceSpec"
```
```
[info] Total number of tests run: 73
[info] Tests: succeeded 73, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
```
67 before, 73 after.
`Test/scalafmtCheck` and `Test/scalafix --check` pass.
### Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 5)
--
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]