import assert from "node:assert/strict"; import { randomUUID } from "node:crypto"; import { readFile, readdir } from "node:fs/promises"; import { PGlite } from "../.data/sql-verification/node_modules/@electric-sql/pglite/dist/index.js"; const db = new PGlite(); try { await db.exec(`create role anon; create role authenticated; create role service_role; create schema auth; create table auth.users(id uuid primary key); create function auth.uid() returns uuid language sql as $$ select null::uuid $$; create schema storage; create table storage.buckets(id text primary key,name text,public boolean,file_size_limit bigint);`); for (const file of (await readdir("supabase/migrations")) .filter((f) => f.endsWith(".sql")) .sort()) await db.exec(await readFile(`supabase/migrations/${file}`, "utf8")); const player = randomUUID(), moderator = randomUUID(), admin = randomUUID(), missing = randomUUID(); for (const [id, role] of [ [player, "contributor"], [moderator, "moderator"], [admin, "admin"], ]) { await db.query("insert into auth.users values($1)", [id]); await db.query("insert into public.profiles(id,role) values($1,$2)", [ id, role, ]); } const makeMap = async () => { const { rows } = await db.query( `insert into public.datasets(owner_id,name,source,bounds,state,panorama_count) values($1,'Permissions fixture','plugin','{"minX":0,"minZ":0,"maxX":64,"maxZ":64}','review',5) returning id`, [player], ); const id = rows[0].id; await db.query( "insert into public.dataset_inputs(dataset_id,manifest,validated) values($1,$2,true)", [ id, JSON.stringify({ name: "Permissions fixture", description: "Role verification", viewpoints: Array.from({ length: 5 }, (_, i) => ({ id: `p${i}`, assetId: `p${i}`, })), }), ], ); return id; }; const id = await makeMap(); const decide = (map, reviewer, decision, reason = null) => db.query("select public.publish_dataset($1,$2,$3,$4)", [ map, reviewer, decision, reason, ]); await assert.rejects( decide(id, player, "approve"), /Moderator permission required/, ); await decide(id, moderator, "approve"); assert.equal( (await db.query("select state from public.datasets where id=$1", [id])) .rows[0].state, "published", ); await assert.rejects( decide(id, moderator, "unpublish"), /Admin permission required/, ); await decide(id, admin, "unpublish"); assert.equal( (await db.query("select state from public.datasets where id=$1", [id])) .rows[0].state, "unpublished", ); const rejected = await makeMap(); await decide( rejected, moderator, "reject", "Please fix the missing terrain.", ); assert.equal( ( await db.query("select state from public.datasets where id=$1", [ rejected, ]) ).rows[0].state, "rejected", ); const updated = await makeMap(); await decide(updated, admin, "approve"); await db.query( "update public.datasets set update_state='review' where id=$1", [updated], ); await decide(updated, moderator, "approve"); assert.equal( ( await db.query("select update_state from public.datasets where id=$1", [ updated, ]) ).rows[0].update_state, null, ); for (const actor of [player, moderator]) { await assert.rejects( db.query("select public.set_beta_badge($1,false)", [actor]), /Admin permission required/, ); await assert.rejects( db.query("select public.set_user_prefix($1,$2,'Spoof','crown')", [ actor, player, ]), /Admin permission required/, ); await assert.rejects( db.query( "select public.review_content_report($1,$2,'dismiss','Valid feedback here')", [missing, actor], ), /Admin permission required/, ); await assert.rejects( db.query( "select public.review_map_appeal($1,$2,'approve','Valid feedback here')", [missing, actor], ), /Admin permission required/, ); } await db.query("select public.set_beta_badge($1,false)", [admin]); assert.equal( (await db.query("select beta_badge_enabled from public.site_settings")) .rows[0].beta_badge_enabled, false, ); await db.query("select public.set_user_prefix($1,$2,'Builder','gem')", [ admin, player, ]); assert.equal( ( await db.query("select custom_prefix from public.profiles where id=$1", [ player, ]) ).rows[0].custom_prefix, "Builder", ); await db.exec( "create role identity_probe bypassrls; grant select,update on public.profiles to identity_probe; grant usage on schema public to identity_probe; set role identity_probe", ); await assert.rejects( db.query("update public.profiles set role='admin' where id=$1", [player]), /Moderator permission required/, ); await db.exec("reset role"); for (const role of ["anon", "authenticated"]) { await db.exec(`set role ${role}`); for (const query of [ [ "select public.publish_dataset($1,$2,'unpublish',null)", [updated, admin], ], ["select public.set_beta_badge($1,true)", [admin]], ["select public.set_user_prefix($1,$2,'Spoof','star')", [admin, player]], [ "select public.review_content_report($1,$2,'dismiss','Valid feedback here')", [missing, admin], ], [ "select public.review_map_appeal($1,$2,'approve','Valid feedback here')", [missing, admin], ], ]) await assert.rejects(db.query(...query), /permission denied/); await db.exec("reset role"); } console.log( "Admin permissions SQL passed: moderators approve/reject maps and updates; administrative actions and role spoofing are blocked; admins retain full access.", ); } finally { await db.close(); }