amber-backend/pb_migrations/1786500001_releases_protect_file.js
Claude 6be486b275 Fix auto-update file gating: mark releases.file protected (#16)
The E2E caught a real leak: a non-nsfw (even anonymous) account could download
an adult artifact. In PocketBase, file protection is a per-FIELD flag, not
derived from the collection view rule — the original migration left releases.file
unprotected, so its URL was public despite the gated read rules.

- Add protected:true to the file field (correct for fresh installs).
- 1786500001_releases_protect_file.js: alter the field on the already-deployed
  instance (applied migrations don't re-run, so the fix needs its own migration).
- Doc: correct the gating explanation (protection is the field flag; the file
  token grant then re-checks the view rule).

With this, a protected file needs a file token whose grant re-checks the view
rule, so a clean account is denied the adult artifact.
2026-07-20 11:48:07 +02:00

25 lines
970 B
JavaScript

/// <reference path="../pb_data/types.d.ts" />
// Fix gating on the releases `file` field (issue #16).
//
// The original migration created the file field without `protected: true`, which
// left the artifact URL PUBLIC — a non-nsfw account (and even an anonymous
// request) could download the adult build, defeating the whole point of the
// gating rules. Protection in PocketBase is a per-field flag, not derived from
// the collection view rule: with it on, the file is served only via a
// short-lived file token whose grant re-checks the view rule.
//
// This alters the field on already-deployed instances; a fresh install gets it
// correct straight from 1786500000.
migrate((app) => {
const c = app.findCollectionByNameOrId("releases")
const f = c.fields.getByName("file")
f.protected = true
app.save(c)
}, (app) => {
const c = app.findCollectionByNameOrId("releases")
const f = c.fields.getByName("file")
f.protected = false
app.save(c)
})