127 lines
4.8 KiB
SQL
127 lines
4.8 KiB
SQL
-- 0003: Add project planning sections and project visual storage
|
|
-- Run after: supabase/migrations/0002_add_freelancer_os_core_tables.sql
|
|
|
|
alter table public.projects
|
|
add column if not exists cover_image_path text,
|
|
add column if not exists cover_image_alt text;
|
|
|
|
create table if not exists public.project_planning_sections (
|
|
id uuid default uuid_generate_v4() primary key,
|
|
user_id uuid references auth.users(id) on delete cascade not null,
|
|
project_id uuid references public.projects(id) on delete cascade not null,
|
|
category text not null,
|
|
title text not null,
|
|
content text,
|
|
metadata jsonb default '{}'::jsonb not null,
|
|
sort_order integer default 0 not null,
|
|
created_at timestamp with time zone default timezone('utc'::text, now()) not null,
|
|
updated_at timestamp with time zone default timezone('utc'::text, now()) not null
|
|
);
|
|
|
|
do $$
|
|
begin
|
|
if not exists (select 1 from pg_constraint where conname = 'project_planning_sections_category_check') then
|
|
alter table public.project_planning_sections
|
|
add constraint project_planning_sections_category_check
|
|
check (
|
|
category in (
|
|
'overview',
|
|
'problem',
|
|
'goal',
|
|
'audience',
|
|
'scope',
|
|
'design_system',
|
|
'color_palette',
|
|
'typography',
|
|
'assets',
|
|
'notes'
|
|
)
|
|
);
|
|
end if;
|
|
end $$;
|
|
|
|
create index if not exists project_planning_sections_user_id_idx
|
|
on public.project_planning_sections(user_id);
|
|
|
|
create index if not exists project_planning_sections_project_id_idx
|
|
on public.project_planning_sections(project_id);
|
|
|
|
create index if not exists project_planning_sections_category_idx
|
|
on public.project_planning_sections(category);
|
|
|
|
alter table public.project_planning_sections enable row level security;
|
|
|
|
drop policy if exists "Users can view their own project planning sections." on public.project_planning_sections;
|
|
create policy "Users can view their own project planning sections." on public.project_planning_sections
|
|
for select using (auth.uid() = user_id);
|
|
|
|
drop policy if exists "Users can insert their own project planning sections." on public.project_planning_sections;
|
|
create policy "Users can insert their own project planning sections." on public.project_planning_sections
|
|
for insert with check (auth.uid() = user_id);
|
|
|
|
drop policy if exists "Users can update their own project planning sections." on public.project_planning_sections;
|
|
create policy "Users can update their own project planning sections." on public.project_planning_sections
|
|
for update using (auth.uid() = user_id);
|
|
|
|
drop policy if exists "Users can delete their own project planning sections." on public.project_planning_sections;
|
|
create policy "Users can delete their own project planning sections." on public.project_planning_sections
|
|
for delete using (auth.uid() = user_id);
|
|
|
|
drop trigger if exists set_project_planning_sections_updated_at on public.project_planning_sections;
|
|
create trigger set_project_planning_sections_updated_at
|
|
before update on public.project_planning_sections
|
|
for each row execute procedure public.set_updated_at();
|
|
|
|
insert into storage.buckets (id, name, public, file_size_limit, allowed_mime_types)
|
|
values (
|
|
'project-assets',
|
|
'project-assets',
|
|
false,
|
|
5242880,
|
|
array['image/jpeg', 'image/png', 'image/webp', 'image/gif']
|
|
)
|
|
on conflict (id) do update set
|
|
public = excluded.public,
|
|
file_size_limit = excluded.file_size_limit,
|
|
allowed_mime_types = excluded.allowed_mime_types;
|
|
|
|
drop policy if exists "Users can view their own project assets." on storage.objects;
|
|
create policy "Users can view their own project assets." on storage.objects
|
|
for select using (
|
|
bucket_id = 'project-assets'
|
|
and (
|
|
public.neta_current_jwt_role() = 'service_role'
|
|
or auth.uid()::text = (storage.foldername(name))[1]
|
|
)
|
|
);
|
|
|
|
drop policy if exists "Users can upload their own project assets." on storage.objects;
|
|
create policy "Users can upload their own project assets." on storage.objects
|
|
for insert with check (
|
|
bucket_id = 'project-assets'
|
|
and (
|
|
public.neta_current_jwt_role() = 'service_role'
|
|
or auth.uid()::text = (storage.foldername(name))[1]
|
|
)
|
|
);
|
|
|
|
drop policy if exists "Users can update their own project assets." on storage.objects;
|
|
create policy "Users can update their own project assets." on storage.objects
|
|
for update using (
|
|
bucket_id = 'project-assets'
|
|
and (
|
|
public.neta_current_jwt_role() = 'service_role'
|
|
or auth.uid()::text = (storage.foldername(name))[1]
|
|
)
|
|
);
|
|
|
|
drop policy if exists "Users can delete their own project assets." on storage.objects;
|
|
create policy "Users can delete their own project assets." on storage.objects
|
|
for delete using (
|
|
bucket_id = 'project-assets'
|
|
and (
|
|
public.neta_current_jwt_role() = 'service_role'
|
|
or auth.uid()::text = (storage.foldername(name))[1]
|
|
)
|
|
);
|