92 lines
3.9 KiB
PL/PgSQL
92 lines
3.9 KiB
PL/PgSQL
-- Migration p2-003: Schemaobjekte der Anwendungsrolle uebereignen
|
|
--
|
|
-- psql "$ADMIN_DATABASE_URL" -v ON_ERROR_STOP=1 -f migrations/p2-003-eigentuemer.sql
|
|
--
|
|
-- Die Datenbank wurzelwerk gehoert der Rolle wurzelwerk, ihre Tabellen aber
|
|
-- postgres: schema.sql wurde beim Ingest-Deploy als Superuser eingespielt.
|
|
-- Folge ist, dass die Anwendungsrolle an ihrem eigenen Schema nichts aendern
|
|
-- darf - jedes `alter table` scheitert mit "must be owner of table".
|
|
--
|
|
-- Die uebrigen Dienste auf derselben Instanz halten es anders herum: gitea
|
|
-- und hedgedoc besitzen ihre Tabellen vollstaendig. Diese Migration stellt
|
|
-- denselben Zustand her. Der Radius bleibt auf die Datenbank wurzelwerk
|
|
-- beschraenkt; an gitea und hedgedoc wird nicht geruehrt.
|
|
--
|
|
-- Danach laufen Migrationen ohne Superuser, also ueber DATABASE_URL statt
|
|
-- ueber den Socket im Container. Ausnahme bleibt `create extension` in
|
|
-- p2-002, sofern die Erweiterung nicht als trusted gefuehrt wird.
|
|
--
|
|
-- Diese Migration ist die einzige, die zwingend als Superuser laeuft - sie
|
|
-- verschenkt Rechte, die sie selbst nicht mehr braeuchte.
|
|
|
|
begin;
|
|
|
|
do $$
|
|
declare
|
|
ziel constant name := 'wurzelwerk';
|
|
o record;
|
|
n integer := 0;
|
|
begin
|
|
if not exists (select 1 from pg_roles where rolname = ziel) then
|
|
raise exception 'Rolle % existiert nicht', ziel;
|
|
end if;
|
|
|
|
-- Tabellen, Sichten und freistehende Sequenzen.
|
|
--
|
|
-- Ausgenommen sind zwei Gruppen. Erstens Objekte einer Erweiterung
|
|
-- (pg_trgm, vector): die gehoeren dem Superuser und werden mit der
|
|
-- Erweiterung verwaltet, nicht von Hand. Zweitens Sequenzen, die an
|
|
-- einer Spalte haengen - alles aus bigserial. Die folgen dem Eigentuemer
|
|
-- ihrer Tabelle von selbst und lassen sich nicht einzeln uebereignen
|
|
-- ("is linked to table"). Deshalb erst die Tabellen, dann der Rest.
|
|
for o in
|
|
select c.oid::regclass::text as name,
|
|
case c.relkind when 'S' then 'sequence'
|
|
when 'v' then 'view'
|
|
when 'm' then 'materialized view'
|
|
else 'table' end as art
|
|
from pg_class c join pg_namespace n on n.oid = c.relnamespace
|
|
where n.nspname = 'public'
|
|
and c.relkind in ('r', 'p', 'S', 'v', 'm')
|
|
and pg_get_userbyid(c.relowner) <> ziel
|
|
and not exists (select 1 from pg_depend d
|
|
where d.classid = 'pg_class'::regclass
|
|
and d.objid = c.oid and d.deptype = 'e')
|
|
and not exists (select 1 from pg_depend d
|
|
where d.classid = 'pg_class'::regclass
|
|
and d.objid = c.oid and d.deptype = 'a'
|
|
and d.refclassid = 'pg_class'::regclass)
|
|
order by case c.relkind when 'r' then 0 when 'p' then 0
|
|
when 'v' then 1 when 'm' then 1 else 2 end
|
|
loop
|
|
execute format('alter %s %s owner to %I', o.art, o.name, ziel);
|
|
n := n + 1;
|
|
end loop;
|
|
|
|
-- Funktionen ebenso. Ohne sie duerfte die Rolle ihre eigenen Helfer
|
|
-- spaeter nicht mehr ersetzen.
|
|
for o in
|
|
select p.oid::regprocedure::text as name
|
|
from pg_proc p join pg_namespace n on n.oid = p.pronamespace
|
|
where n.nspname = 'public'
|
|
and pg_get_userbyid(p.proowner) <> ziel
|
|
and not exists (select 1 from pg_depend d
|
|
where d.classid = 'pg_proc'::regclass
|
|
and d.objid = p.oid and d.deptype = 'e')
|
|
loop
|
|
execute format('alter function %s owner to %I', o.name, ziel);
|
|
n := n + 1;
|
|
end loop;
|
|
|
|
raise notice 'uebereignet: % Objekte an %', n, ziel;
|
|
end $$;
|
|
|
|
-- Neue Objekte gehoeren ohnehin dem, der sie anlegt; das Recht dazu im
|
|
-- Schema public ist seit PostgreSQL 15 nicht mehr selbstverstaendlich.
|
|
grant create, usage on schema public to wurzelwerk;
|
|
|
|
insert into schema_migrationen (name) values ('p2-003-eigentuemer')
|
|
on conflict (name) do nothing;
|
|
|
|
commit;
|