Nothing read `users.nsfwEnabled` any more. `/api/amber/whoami` stopped returning it, `GET /api/update/manifest` always answers `clean`, and the `releases` read rule stopped mentioning it in migration 1793000000, when the nine 18+ rows (437 MB) were deleted. What was left was a per-account flag nobody writes and nobody reads, sitting on the family's accounts and showing up in every schema dump and access-rule review as if it still gated something. A flag that looks like a protection but protects nothing costs the next reader the work of proving it dead. One live reader did remain: pb_public/index.html showed a "Zdroj 18+" source field and wrote `adultAddonUrl` into the encrypted addon config for a flagged account, and picked a different child-profile label for one. Both are gone, so the page offers the same three sources to everyone. Migration 1797000000 drops the field, rewrites users.updateRule to `id = @request.auth.id` (the clause it loses guarded a field that no longer exists), and removes `adult` from releases.variant's allowed values. Checked before writing it: 15 release rows, every one `clean`; three accounts carried the flag (the owner's, one family member's, the retired test account); the separate 18+ app has no accounts and no PocketBase, so nothing outside Amber reads it. `variant` itself stays and stays required: every installed Amber compares it against its own build and refuses a mismatch SILENTLY, so dropping the field would strand those installs with no error to see. publish-release.sh now accepts only `clean`. The status dashboard stops listing `adult-stremio-addon` and `stripchat-proxy`. Both still run on the VPS; they are the owner's, not Amber's, and Amber never reached them. scripts/verify.py asserts the flag stays gone (field absent, no rule mentions it, updateRule own-record-only). Run against a local PocketBase built from origin/main it failed on exactly those three checks; with this migration applied, ALL CHECKS PASSED. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
59 lines
2.3 KiB
JavaScript
59 lines
2.3 KiB
JavaScript
/// <reference path="../pb_data/types.d.ts" />
|
|
|
|
// Auto-update manifest (epic #6, issue #16).
|
|
//
|
|
// GET /api/update/manifest?platform=windows|linux|android (auth: users)
|
|
//
|
|
// Returns the latest published build for the caller's platform. The download is
|
|
// PocketBase's native protected file endpoint: the app mints a short-lived file
|
|
// token (`POST /api/files/token`) and appends it to `downloadPath`, and the token
|
|
// grant re-checks the collection rule.
|
|
//
|
|
// `variant` used to be chosen here from an account flag, picking an 18+ build
|
|
// over the clean one. Amber has no 18+ build any more and the flag is gone
|
|
// (migration 1797000000), so it is a constant.
|
|
//
|
|
// It is NOT removed from the response, and must not be. Every Amber already
|
|
// installed compares this field against its own and refuses a mismatch SILENTLY
|
|
// — no error, no prompt, the update simply never appears. Drop it, or send
|
|
// anything but "clean", and those installs stop updating with nothing to see.
|
|
//
|
|
// NOTE: PocketBase runs each routerAdd handler in its own isolated JSVM, so the
|
|
// small helpers live inside the handler.
|
|
routerAdd("GET", "/api/update/manifest", (e) => {
|
|
const ALLOWED = ["windows", "linux", "android"]
|
|
const platform = (e.request.url.query().get("platform") || "").toLowerCase().trim()
|
|
if (ALLOWED.indexOf(platform) === -1) throw new BadRequestError("bad or missing platform")
|
|
|
|
// One build ships. See the note above for why this field survives at all.
|
|
const variant = "clean"
|
|
|
|
let rec = null
|
|
try {
|
|
const rows = $app.findRecordsByFilter(
|
|
"releases",
|
|
"platform = {:p} && variant = {:v}",
|
|
"-buildNumber",
|
|
1, 0,
|
|
{ p: platform, v: variant }
|
|
)
|
|
if (rows && rows.length) rec = rows[0]
|
|
} catch (_) { /* no matching release */ }
|
|
|
|
if (!rec) return e.json(200, { available: false })
|
|
|
|
const filename = rec.getString("file")
|
|
return e.json(200, {
|
|
available: true,
|
|
platform: platform,
|
|
variant: variant,
|
|
version: rec.getString("version"),
|
|
buildNumber: rec.getInt("buildNumber"),
|
|
notes: rec.getString("notes"),
|
|
sha256: rec.getString("sha256"),
|
|
size: rec.getInt("size"),
|
|
filename: filename,
|
|
// Native protected-file path; the app appends `?token=<file token>`.
|
|
downloadPath: "/api/files/releases/" + rec.id + "/" + filename,
|
|
})
|
|
}, $apis.requireAuth("users"))
|