// One-off backfill: assign an owner to every car that has none. // // Before per-user ownership existed, all cars were ownerless and globally // visible. This sets `owner` on any car missing it so those cars keep showing // up once the API Server starts filtering by owner. Safe to re-run: cars that // already have an owner are skipped. // // Usage (PowerShell): // $env:PB_URL="http://10.2.1.10:8027" // $env:PB_ADMIN_EMAIL="admin@carcontrole.local" // $env:PB_ADMIN_PASSWORD="..." // node scripts/backfill-car-owners.mjs // // Defaults to Dariusz (u7jxozp9jbspp5r) when omitted. const PB_URL = (process.env.PB_URL || "http://10.2.1.10:8027").replace(/\/+$/, ""); const ADMIN_EMAIL = process.env.PB_ADMIN_EMAIL; const ADMIN_PASSWORD = process.env.PB_ADMIN_PASSWORD; const OWNER_ID = process.argv[2] || "u7jxozp9jbspp5r"; // Dariusz if (!ADMIN_EMAIL || !ADMIN_PASSWORD) { console.error("Set PB_ADMIN_EMAIL and PB_ADMIN_PASSWORD."); process.exit(1); } async function authenticate() { for (const ep of [ "/api/collections/_superusers/auth-with-password", "/api/admins/auth-with-password", ]) { const res = await fetch(PB_URL + ep, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ identity: ADMIN_EMAIL, password: ADMIN_PASSWORD }), }); if (res.ok) return (await res.json()).token; } throw new Error("Admin authentication failed."); } async function main() { console.log(`Connecting to ${PB_URL} ...`); const token = await authenticate(); // Verify the target owner exists, so we fail loudly on a bad id. const ures = await fetch(`${PB_URL}/api/collections/users/records/${OWNER_ID}`, { headers: { Authorization: token }, }); if (!ures.ok) throw new Error(`owner user ${OWNER_ID} not found (${ures.status})`); const owner = await ures.json(); console.log(`Backfilling ownerless cars → ${owner.email} (${OWNER_ID})`); const res = await fetch(`${PB_URL}/api/collections/cars/records?perPage=500`, { headers: { Authorization: token }, }); if (!res.ok) throw new Error(`list cars failed: ${res.status} ${await res.text()}`); const cars = (await res.json()).items || []; let updated = 0; for (const car of cars) { if (car.owner) { console.log(`• ${car.name} — already owned (${car.owner})`); continue; } const upd = await fetch(`${PB_URL}/api/collections/cars/records/${car.id}`, { method: "PATCH", headers: { "Content-Type": "application/json", Authorization: token }, body: JSON.stringify({ owner: OWNER_ID }), }); if (!upd.ok) throw new Error(`update ${car.name} failed: ${upd.status} ${await upd.text()}`); console.log(`✓ ${car.name} — owner set`); updated++; } console.log(`\nDone. ${updated} car(s) updated, ${cars.length - updated} already owned.`); } main().catch((err) => { console.error("\nBackfill failed:", err.message); process.exit(1); });