-- Rowpass migration template: one new Supabase table, exposed on purpose -- Grant, row level security and policies in the same migration as the table, -- so the table works after every `supabase db reset` and on every new project. -- Replace your_table and user_id, keep ONE of the three blocks, delete the other two. -- Free to copy, change and share. Read it before you run it. create table public.your_table ( id uuid primary key default gen_random_uuid(), user_id uuid not null references auth.users (id), created_at timestamptz not null default now() ); -- ============================================================ -- A) OWNER ONLY: each signed-in user reads and writes their own rows -- ============================================================ -- public.your_table: owner only alter table public.your_table enable row level security; revoke all on table public.your_table from anon, authenticated; grant select, insert, update, delete on table public.your_table to authenticated; grant select, insert, update, delete on table public.your_table to service_role; drop policy if exists your_table_select_own on public.your_table; create policy your_table_select_own on public.your_table for select to authenticated using ( (select auth.uid()) = user_id ); drop policy if exists your_table_insert_own on public.your_table; create policy your_table_insert_own on public.your_table for insert to authenticated with check ( (select auth.uid()) = user_id ); drop policy if exists your_table_update_own on public.your_table; create policy your_table_update_own on public.your_table for update to authenticated using ( (select auth.uid()) = user_id ) with check ( (select auth.uid()) = user_id ); drop policy if exists your_table_delete_own on public.your_table; create policy your_table_delete_own on public.your_table for delete to authenticated using ( (select auth.uid()) = user_id ); -- ============================================================ -- B) PUBLIC READ: anyone can read, only your server can write -- ============================================================ -- public.your_table: public read alter table public.your_table enable row level security; revoke all on table public.your_table from anon, authenticated; grant select on table public.your_table to anon; grant select on table public.your_table to authenticated; grant select, insert, update, delete on table public.your_table to service_role; drop policy if exists your_table_read_all on public.your_table; create policy your_table_read_all on public.your_table for select to anon, authenticated using ( true ); -- ============================================================ -- C) PRIVATE: only your server (service_role) can reach it -- ============================================================ -- public.your_table: private alter table public.your_table enable row level security; revoke all on table public.your_table from anon, authenticated; grant select, insert, update, delete on table public.your_table to service_role; -- no policies: with RLS on and no policy, anon and authenticated read nothing. -- service_role bypasses RLS. Keep its key on your server only. -- If the id column is serial or bigserial, inserts also need the sequence: -- grant usage, select on sequence public.your_table_id_seq to authenticated, service_role;