diff --git a/scripts/seed-providers.py b/scripts/seed-providers.py index eae4532..28a0155 100644 --- a/scripts/seed-providers.py +++ b/scripts/seed-providers.py @@ -14,13 +14,21 @@ Without `--force` an existing row is left alone and reported as `kept`, which makes this safe to run after any deploy — the collection gets populated on a fresh instance and untouched on one that is already looked after. -Never reads secrets/amber.env: the superuser credentials come from the -environment or from the local defaults, the same way scripts/verify.py takes -them, so nothing here needs access to the family's credential file. +Authenticates one of two ways, in this order: + + PB_ADMIN_TOKEN an existing superuser token, used as-is + PB_ADMIN_EMAIL/PB_ADMIN_PASS a superuser sign-in (local default below) + +The token path exists because that is what the production instance is reachable +with: `secrets/amber.env` holds `PB_ADMIN_TOKEN` and no superuser password, and +inventing one to satisfy this script would be the wrong way round. Never reads that +file itself, so nothing here needs access to the family's credentials, and never +prints the token. """ import json, os, pathlib, sys, urllib.error, urllib.request BASE = os.environ.get("PB_BASE", "http://localhost:8090").rstrip("/") +ADMIN_TOKEN = os.environ.get("PB_ADMIN_TOKEN", "").strip() ADMIN_EMAIL = os.environ.get("PB_ADMIN_EMAIL", "admin@myanime.local") ADMIN_PASS = os.environ.get("PB_ADMIN_PASS", "Sup3rSecret!123") FORCE = "--force" in sys.argv @@ -53,11 +61,29 @@ def main(): if unknown: sys.exit(f"unknown slug(s) {sorted(unknown)} — the page has no wiring for these") - st, auth = req("POST", "/api/collections/_superusers/auth-with-password", - body={"identity": ADMIN_EMAIL, "password": ADMIN_PASS}) + if ADMIN_TOKEN: + token = ADMIN_TOKEN + else: + st, auth = req("POST", "/api/collections/_superusers/auth-with-password", + body={"identity": ADMIN_EMAIL, "password": ADMIN_PASS}) + if st != 200: + sys.exit(f"superuser auth failed against {BASE}: HTTP {st} {auth}") + token = auth["token"] + + # Prove the token is really a superuser BEFORE reading anything, against an + # endpoint only a superuser may touch. + # + # Listing records cannot answer this. PocketBase applies a collection's listRule + # as a *filter*, so a stale token comes back HTTP 200 with zero rows — identical + # to a collection that is simply empty. The seeder then decides every provider is + # missing and tries to create all four, and the first thing you see is + # "[FAIL] prehrajto: HTTP 403 Only superusers can perform this action", which + # points at the row instead of at the token. Measured, not assumed. + st, who = req("GET", "/api/collections?perPage=1", token) if st != 200: - sys.exit(f"superuser auth failed against {BASE}: HTTP {st} {auth}") - token = auth["token"] + sys.exit(f"HTTP {st} against {BASE}: this is not a valid superuser token. " + "Refresh PB_ADMIN_TOKEN in secrets/amber.env and do not work " + "around it.") st, existing = req("GET", "/api/collections/providers/records?perPage=200", token) if st != 200: