Release v0.1.4 with terrain rescanning and owner-published map updates
All checks were successful
Deploy MineGeo to Dokploy / deploy (push) Successful in 6m26s

This commit is contained in:
2026-10-28 19:40:53 +05:00
parent 5898ef35a5
commit 658c8974ac
53 changed files with 608 additions and 83 deletions

View File

@@ -0,0 +1,84 @@
-- Keep the legacy column and API shape while allowing comma-separated aliases.
create or replace function public.assert_capture_server(p_expected text,p_actual text) returns void
language plpgsql security invoker set search_path='' as $$
declare expected text; actual text; allowed text[] := '{}';
begin
if nullif(trim(p_expected),'') is null then return; end if;
foreach expected in array string_to_array(p_expected,',') loop
expected := public.normalize_server_address(expected);
if expected is null then raise exception 'Empty server address'; end if;
allowed := array_append(allowed,expected);
end loop;
actual := public.normalize_server_address(p_actual);
if actual is null or not (actual = any(allowed)) then
raise exception 'Wrong capture server: use one of %, but the export records %.', array_to_string(allowed, ', '), coalesce(actual,'no server address');
end if;
end; $$;
create or replace function public.set_contribution_server(p_dataset uuid,p_owner uuid,p_address text) returns void
language plpgsql security invoker set search_path='' as $$
declare address text; addresses text[] := '{}';
begin
perform 1 from public.datasets where id=p_dataset and owner_id=p_owner and parent_dataset_id is null for update;
if not found then raise exception 'Map owner permission required'; end if;
if nullif(trim(p_address),'') is not null then
foreach address in array string_to_array(p_address,',') loop
address := public.normalize_server_address(address);
if address is null then raise exception 'Empty server address'; end if;
if not address=any(addresses) then addresses:=array_append(addresses,address); end if;
end loop;
if cardinality(addresses)>10 then raise exception 'At most 10 server addresses are allowed'; end if;
end if;
update public.datasets set contribution_server_address=nullif(array_to_string(addresses,','),''),updated_at=now() where id=p_dataset;
end; $$;
-- Legacy uploaders can defer alias validation to the server; updated uploaders
-- use the complete list before transferring files.
create or replace function public.contribution_server(p_dataset uuid,p_owner uuid) returns jsonb
language plpgsql security invoker set search_path='' as $$
declare d public.datasets; addresses text[];
begin
select * into d from public.datasets where id=p_dataset and parent_dataset_id is null;
if not found then raise exception 'Map not found'; end if;
if d.owner_id<>p_owner and not d.allow_contributions then raise exception 'The owner has disabled player contributions'; end if;
addresses:=case when d.contribution_server_address is null then '{}'::text[] else string_to_array(d.contribution_server_address,',') end;
return jsonb_build_object('serverAddress',case when cardinality(addresses)=1 then addresses[1] else null end,'serverAddresses',to_jsonb(addresses));
end; $$;
-- Only already approved, owned maps can publish a validated draft directly.
create function public.publish_owner_update(p_dataset uuid,p_owner uuid) returns void
language plpgsql security invoker set search_path='' as $$
declare d public.datasets; m jsonb; rev uuid; first jsonb; n integer;
begin
select * into d from public.datasets where id=p_dataset and owner_id=p_owner for update;
if not found or d.parent_dataset_id is not null or d.imported_from_id is not null then raise exception 'Map owner permission required'; end if;
if d.state <> 'published' or d.banned_at is not null or coalesce(d.update_state,'') not in ('draft','rejected') then raise exception 'Published map update is not ready'; end if;
if exists(select 1 from public.upload_jobs where dataset_id=d.id and state in ('queued','running')) then raise exception 'Wait for map rendering to finish'; end if;
select manifest into m from public.dataset_inputs where dataset_id=d.id and validated;
n:=jsonb_array_length(m->'viewpoints'); first:=m->'viewpoints'->0;
if m is null or n<5 or n>24 then raise exception 'Map requires 5–24 validated panoramas'; end if;
insert into public.revisions(dataset_id,manifest,asset_root) values(d.id,m,d.id::text) returning id into rev;
update public.datasets set revision_id=rev,update_state=null,name=m->>'name',description=m->>'description',panorama_count=n,map_path=coalesce(m->>'mapPath',d.map_path),
cover_path=coalesce(first->>'assetRoot',id::text)||'/'||coalesce(first->>'assetId',first->>'id')||'/preview.webp',rejection_reason=null,updated_at=now() where id=d.id;
end; $$;
revoke execute on function public.publish_owner_update(uuid,uuid) from public,anon,authenticated;
grant execute on function public.publish_owner_update(uuid,uuid) to service_role;
-- Publish an owner's own processed contribution in one transaction. A map
-- with other draft edits must be reviewed separately by its owner first.
create function public.publish_own_contribution(p_contribution uuid,p_owner uuid) returns void
language plpgsql security invoker set search_path='' as $$
declare child public.datasets; root public.datasets;
begin
select * into child from public.datasets where id=p_contribution and owner_id=p_owner;
if not found or child.parent_dataset_id is null then raise exception 'Owner contribution required'; end if;
select * into root from public.datasets where id=child.parent_dataset_id and owner_id=p_owner for update;
if not found or root.state<>'published' or root.update_state is not null or root.banned_at is not null or root.imported_from_id is not null then
raise exception 'Publish or discard the existing map draft first';
end if;
perform public.submit_draft(child.id,p_owner);
perform public.review_contribution(root.id,child.id,p_owner,'accept');
perform public.publish_owner_update(root.id,p_owner);
end; $$;
revoke execute on function public.publish_own_contribution(uuid,uuid) from public,anon,authenticated;
grant execute on function public.publish_own_contribution(uuid,uuid) to service_role;

View File

@@ -0,0 +1,15 @@
-- The Void difficulty migration recreated this function without retaining the
-- active-account check added by account controls.
do $$
declare definition text;
begin
definition := pg_get_functiondef('public.read_prometheus_metrics(text)'::regprocedure);
if position('p.role=''admin'' and p.account_status=''active''' in definition) > 0 then
return;
end if;
if position('p.role=''admin''' in definition) = 0 then
raise exception 'Metrics authorization definition is unexpected';
end if;
definition := replace(definition, 'p.role=''admin''', 'p.role=''admin'' and p.account_status=''active''');
execute definition;
end; $$;