-- Self-contained fixtures; safe to run on the configured project (rolls back). begin; do $$ declare owner uuid; moderator uuid; reporter uuid; second uuid; third uuid; fourth uuid; fixture uuid; revision uuid; report uuid; appeal uuid; r2 uuid; r3 uuid; r4 uuid; begin -- Reuse accounts on the configured project; seed accounts in the isolated runtime. if not exists(select 1 from auth.users) then insert into auth.users(id) select gen_random_uuid() from generate_series(1,6); end if; select id into owner from auth.users order by id limit 1; select id into moderator from auth.users where id<>owner order by id limit 1; select id into reporter from auth.users where id not in (owner,moderator) order by id limit 1; select id into second from auth.users where id not in (owner,moderator,reporter) order by id limit 1; select id into third from auth.users where id not in (owner,moderator,reporter,second) order by id limit 1; select id into fourth from auth.users where id not in (owner,moderator,reporter,second,third) order by id limit 1; if fourth is null then raise exception 'Six fixture accounts are required'; end if; insert into public.profiles(id) values(owner),(moderator),(reporter),(second),(third),(fourth) on conflict(id) do nothing; update public.profiles set role='admin' where id=moderator; update public.profiles set role='contributor' where id in (owner,reporter,second,third,fourth); insert into public.datasets(owner_id,name,source,bounds,state,panorama_count) values(owner,'Report regression','plugin','{"minX":0,"minZ":0,"maxX":64,"maxZ":64}','published',5) returning id into fixture; insert into public.revisions(dataset_id,asset_root,manifest) values(fixture,fixture::text,'{"viewpoints":[{"id":"p0"}]}') returning id into revision; update public.datasets set revision_id=revision where id=fixture; report:=public.submit_content_report(fixture,reporter,revision,'p0','broken','The panorama has missing terrain.'); if (select report_strikes from public.datasets where id=fixture)<>0 then raise exception 'Unreviewed report added a strike'; end if; begin perform public.submit_content_report(fixture,reporter,revision,null,'spam','A second report from the same person.'); raise exception 'Duplicate report succeeded'; exception when others then if sqlerrm not like 'You already reported%' then raise; end if; end; begin perform public.submit_content_report(fixture,owner,revision,null,'spam','An owner reported their own map.'); raise exception 'Self-report succeeded'; exception when others then if sqlerrm<>'You cannot report your own map' then raise; end if; end; begin perform public.submit_content_report(fixture,second,revision,'unknown','broken','A panorama outside this revision.'); raise exception 'Invalid panorama accepted'; exception when others then if sqlerrm<>'Reported panorama not found' then raise; end if; end; begin perform public.review_content_report(report,owner,'confirm','Confirmed by the map owner.'); raise exception 'Unauthorized moderator succeeded'; exception when others then if sqlerrm<>'Admin permission required' then raise; end if; end; perform public.review_content_report(report,moderator,'dismiss','The reported terrain looks correct.'); if (select report_strikes from public.datasets where id=fixture)<>0 then raise exception 'Dismissed report added a strike'; end if; report:=public.submit_content_report(fixture,reporter,revision,null,'spam','The map contains inappropriate advertisements.'); perform public.review_content_report(report,moderator,'confirm','Confirmed advertising throughout the map.'); begin perform public.review_content_report(report,moderator,'confirm','Replayed moderation request.'); raise exception 'Repeated review added a strike'; exception when others then if sqlerrm<>'Report is no longer awaiting review' then raise; end if; end; r2:=public.submit_content_report(fixture,second,revision,null,'privacy','The map displays personal information.'); r3:=public.submit_content_report(fixture,third,revision,'p0','inappropriate','Offensive content in this panorama.'); r4:=public.submit_content_report(fixture,fourth,revision,null,'spam','Another pending community report.'); perform public.review_content_report(r2,moderator,'confirm','Confirmed private information in the map.'); if not exists(select 1 from public.datasets where id=fixture and report_strikes=2 and state='published' and banned_at is null) then raise exception 'Map unpublished too early'; end if; perform public.review_content_report(r3,moderator,'confirm','Confirmed offensive content in this panorama.'); if not exists(select 1 from public.datasets where id=fixture and report_strikes=3 and state='unpublished' and banned_at is not null) then raise exception 'Third strike did not ban map'; end if; begin perform public.create_game(fixture,'normal',null,'test-guest'); raise exception 'Banned map started a new game'; exception when others then if sqlerrm<>'Map unavailable' then raise; end if; end; begin perform public.submit_draft(fixture,owner); raise exception 'Owner resubmitted a banned map'; exception when others then if sqlerrm<>'Draft is not ready for submission' then raise; end if; end; begin update public.datasets set state='published' where id=fixture; raise exception 'Ban bypass succeeded'; exception when check_violation then null; end; begin perform public.appeal_map_ban(fixture,reporter,'Please restore someone else''s map.'); raise exception 'Non-owner appeal succeeded'; exception when others then if sqlerrm<>'Map owner permission required' then raise; end if; end; appeal:=public.appeal_map_ban(fixture,owner,'Please reconsider these reports and restore my map.'); begin perform public.appeal_map_ban(fixture,owner,'Another appeal while the first is pending.'); raise exception 'Duplicate appeal succeeded'; exception when others then if sqlerrm<>'An appeal is already awaiting review' then raise; end if; end; perform public.review_map_appeal(appeal,moderator,'reject','The violations are present and the ban remains.'); if (select banned_at from public.datasets where id=fixture) is null then raise exception 'Rejected appeal lifted ban'; end if; appeal:=public.appeal_map_ban(fixture,owner,'Here is new context explaining why the reports were mistaken.'); perform public.review_map_appeal(appeal,moderator,'approve','Evidence confirms the map should be restored.'); if not exists(select 1 from public.datasets where id=fixture and report_strikes=0 and state='published' and banned_at is null and report_cycle=1 and revision_id=revision) then raise exception 'Appeal did not restore approved version'; end if; if (select state from public.reports where id=r4)<>'dismissed' then raise exception 'Stale reports survived appeal'; end if; if (select count(*) from public.reports where dataset_id=fixture and state='confirmed')<>3 then raise exception 'Report history was lost'; end if; perform public.submit_content_report(fixture,reporter,revision,null,'broken','A new issue after the approved appeal.'); if has_function_privilege('authenticated','public.review_content_report(uuid,uuid,text,text)','EXECUTE') or has_function_privilege('anon','public.appeal_map_ban(uuid,uuid,text)','EXECUTE') then raise exception 'Privileged function exposed'; end if; if not (select relrowsecurity from pg_class where oid='public.map_appeals'::regclass) then raise exception 'Appeal RLS is disabled'; end if; if has_table_privilege('authenticated','public.map_appeals','SELECT') or has_table_privilege('anon','public.map_appeals','INSERT') then raise exception 'Appeal history exposed to public API'; end if; end; $$; rollback;