Spaces:
Sleeping
Sleeping
File size: 6,061 Bytes
3493993 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | -- Minimum authoritative Project -> Asset / durable Generation Job links.
-- Apply after projects/0001 and security/0003_generation_domain_postgres.sql.
begin;
alter table media_assets add column if not exists project_id text;
do $$
begin
if not exists (
select 1 from pg_constraint
where conname = 'fk_media_assets_project'
and conrelid = 'media_assets'::regclass
) then
alter table media_assets
add constraint fk_media_assets_project
foreign key (project_id) references projects(id) on delete restrict;
end if;
end $$;
create index if not exists ix_media_assets_workspace_project_created
on media_assets(workspace_id, project_id, created_at desc);
create or replace function mediarouter_assert_media_asset_project_workspace()
returns trigger language plpgsql as $$
declare project_workspace text;
declare project_status text;
begin
if tg_op = 'UPDATE' and new.workspace_id is distinct from old.workspace_id then
raise exception 'canonical asset workspace is immutable' using errcode = '23514';
end if;
if new.project_id is not null then
select workspace_id, status into project_workspace, project_status from projects
where id = new.project_id;
if project_workspace is null or project_workspace is distinct from new.workspace_id then
raise exception 'project asset must belong to its project workspace'
using errcode = '23503';
end if;
if project_status is distinct from 'active' then
raise exception 'canonical assets cannot be attached to an archived project'
using errcode = '23514';
end if;
end if;
return new;
end;
$$;
drop trigger if exists mediarouter_media_asset_project_workspace on media_assets;
create trigger mediarouter_media_asset_project_workspace
before insert or update of workspace_id, project_id on media_assets
for each row execute function mediarouter_assert_media_asset_project_workspace();
create table if not exists project_generation_jobs (
id text primary key default gen_random_uuid()::text,
workspace_id text not null references workspaces(id) on delete restrict,
project_id text not null references projects(id) on delete restrict,
generation_job_id text not null references generation_jobs(id) on delete restrict,
attached_by text not null references users(id) on delete restrict,
created_at timestamptz not null default now(),
constraint uq_project_generation_job unique (generation_job_id)
);
create index if not exists ix_project_generation_jobs_workspace_project_created
on project_generation_jobs(workspace_id, project_id, created_at desc);
create or replace function mediarouter_assert_project_generation_job_workspace()
returns trigger language plpgsql as $$
declare project_workspace text;
declare project_status text;
declare job_workspace text;
begin
if tg_op = 'UPDATE' and (
new.workspace_id is distinct from old.workspace_id
or new.project_id is distinct from old.project_id
or new.generation_job_id is distinct from old.generation_job_id
or new.attached_by is distinct from old.attached_by
) then
raise exception 'project generation job ownership is immutable'
using errcode = '23514';
end if;
select workspace_id, status into project_workspace, project_status
from projects where id = new.project_id;
select workspace_id into job_workspace
from generation_jobs where id = new.generation_job_id;
if project_workspace is null
or job_workspace is null
or project_workspace is distinct from new.workspace_id
or job_workspace is distinct from new.workspace_id then
raise exception 'project generation job resources must share a workspace'
using errcode = '23503';
end if;
if project_status is distinct from 'active' then
raise exception 'generation jobs cannot be attached to an archived project'
using errcode = '23514';
end if;
if not exists (
select 1 from workspace_memberships m
where m.workspace_id = new.workspace_id
and m.user_id = new.attached_by
and m.status = 'active'
) then
raise exception 'generation job attachment requires active workspace membership'
using errcode = '23503';
end if;
return new;
end;
$$;
drop trigger if exists mediarouter_project_generation_job_workspace
on project_generation_jobs;
create trigger mediarouter_project_generation_job_workspace
before insert or update on project_generation_jobs
for each row execute function mediarouter_assert_project_generation_job_workspace();
alter table project_generation_jobs enable row level security;
alter table project_generation_jobs force row level security;
drop policy if exists project_generation_jobs_select on project_generation_jobs;
create policy project_generation_jobs_select on project_generation_jobs for select using (
workspace_id = current_setting('app.workspace_id', true)
and exists (
select 1 from workspace_memberships m
where m.workspace_id = project_generation_jobs.workspace_id
and m.user_id = current_setting('app.user_id', true)
and m.status = 'active'
)
);
drop policy if exists project_generation_jobs_insert on project_generation_jobs;
create policy project_generation_jobs_insert on project_generation_jobs for insert with check (
workspace_id = current_setting('app.workspace_id', true)
and attached_by = current_setting('app.user_id', true)
and exists (
select 1 from workspace_memberships m
where m.workspace_id = project_generation_jobs.workspace_id
and m.user_id = current_setting('app.user_id', true)
and m.status = 'active'
)
);
drop policy if exists project_generation_jobs_delete on project_generation_jobs;
create policy project_generation_jobs_delete on project_generation_jobs for delete using (
workspace_id = current_setting('app.workspace_id', true)
and exists (
select 1 from workspace_memberships m
where m.workspace_id = project_generation_jobs.workspace_id
and m.user_id = current_setting('app.user_id', true)
and m.status = 'active'
)
);
commit;
|