diff --git a/supabase/migrations/20260812084115_salon_images_storage_policies.sql b/supabase/migrations/20260812084115_salon_images_storage_policies.sql new file mode 100644 index 0000000..a36afd1 --- /dev/null +++ b/supabase/migrations/20260812084115_salon_images_storage_policies.sql @@ -0,0 +1,17 @@ +-- The salon-images bucket was created manually in the live project during +-- Phase 2A's Task 8 (private, no policies — reserved for this task). Local +-- dev stacks don't have it at all (it wasn't created via migration), so +-- this creates it if missing and makes it public either way: product/ +-- service photos are marketing images meant to be publicly visible once the +-- public site (Sub-project C) reads live data. +insert into storage.buckets (id, name, public) +values ('salon-images', 'salon-images', true) +on conflict (id) do update set public = true; + +create policy "salon_images_public_read" on storage.objects + for select using (bucket_id = 'salon-images'); + +create policy "salon_images_admin_write" on storage.objects + for all + using (bucket_id = 'salon-images' and (select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid) + with check (bucket_id = 'salon-images' and (select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid); diff --git a/supabase/tests/database/rls.test.sql b/supabase/tests/database/rls.test.sql index 6a5436d..9866149 100644 --- a/supabase/tests/database/rls.test.sql +++ b/supabase/tests/database/rls.test.sql @@ -1,5 +1,5 @@ begin; -select plan(12); +select plan(15); -- Seed reference data as service_role (bypasses RLS) set local role service_role; @@ -101,5 +101,27 @@ select lives_ok( 'admin can insert into services' ); +-- salon-images bucket: anyone can read, only admin can write +set local role anon; +set local request.jwt.claim.sub = '00000000-0000-0000-0000-000000000000'; +select lives_ok( + $$ select * from storage.objects where bucket_id = 'salon-images' $$, + 'anon can read salon-images objects' +); + +select throws_ok( + $$ insert into storage.objects (bucket_id, name) values ('salon-images', 'test.jpg') $$, + '42501', + null, + 'anon cannot upload to salon-images' +); + +set local role authenticated; +set local request.jwt.claim.sub = '21c90224-e0b2-412e-a431-8e7f097c1cef'; +select lives_ok( + $$ insert into storage.objects (bucket_id, name) values ('salon-images', 'admin-test.jpg') $$, + 'admin can upload to salon-images' +); + select * from finish(); rollback;