Marketplace inversée (Next.js 16 App Router + Supabase Cloud) : auth, schéma + RLS, publication de besoins avec upload d'images, feed avec filtres, offres, acceptation via RPC, messagerie temps réel, dashboards, et Dockerfile pour déploiement Coolify.
193 lines
6.7 KiB
SQL
193 lines
6.7 KiB
SQL
-- Corrections suite au linter de performance Supabase (get_advisors) :
|
|
-- 1. Wrap auth.uid() en (select auth.uid()) dans toutes les policies RLS
|
|
-- (évite une réévaluation par ligne — recommandation officielle Supabase).
|
|
-- 2. Index sur toutes les clés étrangères signalées.
|
|
|
|
-- ---- profiles ----
|
|
drop policy if exists "profiles_update_own" on public.profiles;
|
|
create policy "profiles_update_own"
|
|
on public.profiles for update
|
|
to authenticated
|
|
using ((select auth.uid()) = id)
|
|
with check ((select auth.uid()) = id);
|
|
|
|
-- ---- needs ----
|
|
drop policy if exists "needs_select" on public.needs;
|
|
create policy "needs_select"
|
|
on public.needs for select
|
|
using (status = 'open' or (select auth.uid()) = author_id);
|
|
|
|
drop policy if exists "needs_insert_own" on public.needs;
|
|
create policy "needs_insert_own"
|
|
on public.needs for insert
|
|
to authenticated
|
|
with check ((select auth.uid()) = author_id);
|
|
|
|
drop policy if exists "needs_update_own" on public.needs;
|
|
create policy "needs_update_own"
|
|
on public.needs for update
|
|
to authenticated
|
|
using ((select auth.uid()) = author_id)
|
|
with check ((select auth.uid()) = author_id);
|
|
|
|
-- ---- need_images ----
|
|
drop policy if exists "need_images_select" on public.need_images;
|
|
create policy "need_images_select"
|
|
on public.need_images for select
|
|
using (
|
|
exists (
|
|
select 1 from public.needs n
|
|
where n.id = need_id and (n.status = 'open' or (select auth.uid()) = n.author_id)
|
|
)
|
|
);
|
|
|
|
drop policy if exists "need_images_insert_own" on public.need_images;
|
|
create policy "need_images_insert_own"
|
|
on public.need_images for insert
|
|
to authenticated
|
|
with check (
|
|
exists (select 1 from public.needs n where n.id = need_id and n.author_id = (select auth.uid()))
|
|
);
|
|
|
|
drop policy if exists "need_images_delete_own" on public.need_images;
|
|
create policy "need_images_delete_own"
|
|
on public.need_images for delete
|
|
to authenticated
|
|
using (
|
|
exists (select 1 from public.needs n where n.id = need_id and n.author_id = (select auth.uid()))
|
|
);
|
|
|
|
-- ---- offers ----
|
|
drop policy if exists "offers_select" on public.offers;
|
|
create policy "offers_select"
|
|
on public.offers for select
|
|
to authenticated
|
|
using (
|
|
(select auth.uid()) = merchant_id
|
|
or exists (select 1 from public.needs n where n.id = need_id and n.author_id = (select auth.uid()))
|
|
);
|
|
|
|
drop policy if exists "offers_insert" on public.offers;
|
|
create policy "offers_insert"
|
|
on public.offers for insert
|
|
to authenticated
|
|
with check (
|
|
merchant_id = (select auth.uid())
|
|
and exists (
|
|
select 1 from public.needs n
|
|
where n.id = need_id and n.status = 'open' and n.author_id <> (select auth.uid())
|
|
)
|
|
);
|
|
|
|
drop policy if exists "offers_update_own_pending" on public.offers;
|
|
create policy "offers_update_own_pending"
|
|
on public.offers for update
|
|
to authenticated
|
|
using ((select auth.uid()) = merchant_id and status = 'pending')
|
|
with check ((select auth.uid()) = merchant_id);
|
|
|
|
-- ---- offer_images ----
|
|
drop policy if exists "offer_images_select" on public.offer_images;
|
|
create policy "offer_images_select"
|
|
on public.offer_images for select
|
|
to authenticated
|
|
using (
|
|
exists (
|
|
select 1 from public.offers o
|
|
where o.id = offer_id
|
|
and (
|
|
o.merchant_id = (select auth.uid())
|
|
or exists (select 1 from public.needs n where n.id = o.need_id and n.author_id = (select auth.uid()))
|
|
)
|
|
)
|
|
);
|
|
|
|
drop policy if exists "offer_images_insert_own" on public.offer_images;
|
|
create policy "offer_images_insert_own"
|
|
on public.offer_images for insert
|
|
to authenticated
|
|
with check (
|
|
exists (select 1 from public.offers o where o.id = offer_id and o.merchant_id = (select auth.uid()))
|
|
);
|
|
|
|
-- ---- conversations ----
|
|
drop policy if exists "conversations_select" on public.conversations;
|
|
create policy "conversations_select"
|
|
on public.conversations for select
|
|
to authenticated
|
|
using ((select auth.uid()) = author_id or (select auth.uid()) = merchant_id);
|
|
|
|
-- ---- messages ----
|
|
drop policy if exists "messages_select" on public.messages;
|
|
create policy "messages_select"
|
|
on public.messages for select
|
|
to authenticated
|
|
using (
|
|
exists (
|
|
select 1 from public.conversations c
|
|
where c.id = conversation_id and ((select auth.uid()) = c.author_id or (select auth.uid()) = c.merchant_id)
|
|
)
|
|
);
|
|
|
|
drop policy if exists "messages_insert" on public.messages;
|
|
create policy "messages_insert"
|
|
on public.messages for insert
|
|
to authenticated
|
|
with check (
|
|
sender_id = (select auth.uid())
|
|
and exists (
|
|
select 1 from public.conversations c
|
|
where c.id = conversation_id and ((select auth.uid()) = c.author_id or (select auth.uid()) = c.merchant_id)
|
|
)
|
|
);
|
|
|
|
-- ---- storage.objects (offer-images) ----
|
|
drop policy if exists "offer_images_bucket_read" on storage.objects;
|
|
create policy "offer_images_bucket_read"
|
|
on storage.objects for select
|
|
to authenticated
|
|
using (
|
|
bucket_id = 'offer-images'
|
|
and exists (
|
|
select 1
|
|
from public.offer_images oi
|
|
join public.offers o on o.id = oi.offer_id
|
|
where oi.storage_path = storage.objects.name
|
|
and (
|
|
o.merchant_id = (select auth.uid())
|
|
or exists (select 1 from public.needs n where n.id = o.need_id and n.author_id = (select auth.uid()))
|
|
)
|
|
)
|
|
);
|
|
|
|
drop policy if exists "need_images_bucket_write" on storage.objects;
|
|
create policy "need_images_bucket_write"
|
|
on storage.objects for insert
|
|
to authenticated
|
|
with check (
|
|
bucket_id = 'need-images'
|
|
and (storage.foldername(name))[1] = (select auth.uid())::text
|
|
);
|
|
|
|
drop policy if exists "offer_images_bucket_write" on storage.objects;
|
|
create policy "offer_images_bucket_write"
|
|
on storage.objects for insert
|
|
to authenticated
|
|
with check (
|
|
bucket_id = 'offer-images'
|
|
and (storage.foldername(name))[1] = (select auth.uid())::text
|
|
);
|
|
|
|
-- ---- Index sur les clés étrangères ----
|
|
create index if not exists idx_needs_author_id on public.needs (author_id);
|
|
create index if not exists idx_needs_category_id on public.needs (category_id);
|
|
create index if not exists idx_needs_accepted_offer_id on public.needs (accepted_offer_id);
|
|
create index if not exists idx_need_images_need_id on public.need_images (need_id);
|
|
create index if not exists idx_offers_merchant_id on public.offers (merchant_id);
|
|
create index if not exists idx_offer_images_offer_id on public.offer_images (offer_id);
|
|
create index if not exists idx_conversations_need_id on public.conversations (need_id);
|
|
create index if not exists idx_conversations_author_id on public.conversations (author_id);
|
|
create index if not exists idx_conversations_merchant_id on public.conversations (merchant_id);
|
|
create index if not exists idx_messages_conversation_id on public.messages (conversation_id);
|
|
create index if not exists idx_messages_sender_id on public.messages (sender_id);
|