tanishqgandhi1908 opened a new pull request, #7937:
URL: https://github.com/apache/texera/pull/7937
### What changes were proposed in this PR?
#7922 gave models the file API the management UI needs. This PR adds the
last backend pieces, so model sharing and the hub can be built as frontend-only
work.
**Cover images** — `POST /{mid}/update/cover`, `GET /{mid}/cover` (307
redirect), `GET /{mid}/cover-url` (JSON, since `<img src>` cannot attach the
Authorization header on a private model). The `cover_image` column already
existed.
The resource-agnostic halves move into a shared `CoverImageUtils` and
`DatasetResource` is refactored onto it, net **−55 lines** there. The image
extension allowlist is a security control, not a convention — a cover is handed
to the browser as a presigned URL, so an active document (`.svg`, `.html`)
would be a stored-XSS vector, and a duplicated allowlist drifts.
**Anonymous version browsing** — `/{mid}/publicVersion/list` and
`/{mid}/publicVersion/{mvid}/rootFileNodes`. Without these a logged-out visitor
on a public model page gets metadata and then an error.
**Framework/format editing** — `POST /update/framework`, `POST
/update/format`, plus `other` in both whitelists. The labels were create-only,
so a mislabelled model had to be recreated.
**Routing** — `/api/model` and `/api/access/model` in nginx, the k8s gateway
and the frontend dev proxy. Nothing reaches the resource in a real deployment
without them. The nginx location needs a trailing slash: nginx matches prefixes
byte-wise, so a bare `/api/model` would swallow the LLM `/api/models` route.
The Gateway API matches whole path segments and does not have that problem.
One behavior change on the dataset side: covers now get a path-length check.
`dataset.cover_image` is `varchar(246)` via `sql/updates/18.sql`, so an
over-long path was a jOOQ-wrapped 500 and is now a 400.
### Any related issues, documentation, discussions?
- Part of #6501
- Stacked on #7922, which is stacked on #6872 and #6869; base is `main`, so
the
diff carries those commits until they merge.
### How was this PR tested?
New `CoverImageUtilsSpec` (18 cases) pins the allowlist, `.svg`/`.html`
rejection, path traversal, absolute paths and both column-width limits. New
`ModelHubApiSpec` (21 cases) drives the covers end to end through LakeFS/MinIO
and covers anonymous browsing, including the negative cases: private model
anonymous and no-grant, unknown model and version id, a model unpublished after
the fact, and agreement between the public and authenticated file-tree
endpoints. `ModelApiForUiSpec` gains the framework/format update cases.
`ModelResourcePermissionsSpec` needed the four new `@PermitAll` endpoint
names — the guardrail caught them, as intended. `DatasetResourceSpec`'s 152
tests pass unmodified after the refactor.
sbt "FileService/testOnly *CoverImageUtilsSpec *ModelHubApiSpec
*ModelApiForUiSpec *ModelResourcePermissionsSpec *ModelDownloadResourceSpec
*ModelResourceSpec *DatasetResourceSpec *DatasetResourcePermissionsSpec"
sbt scalafmtCheckAll "scalafixAll --check"
### 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]