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.
25 lines
970 B
JavaScript
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)
|
|
})
|