import { safeSql } from '@supabase/pg-meta/src/pg-format' import { PolicyTemplate } from '../PolicyTemplates/PolicyTemplates.constants' /** * ---------------------------------------------------------------- * PostgreSQL policy templates for the auth policies page * ---------------------------------------------------------------- * id: Unique identifier for the monaco editor to dynamically refresh * templateName: As a display for a more descriptive title for the policy * description: Additional details about the template and how to make it yours * statement: SQL statement template for the policy * * name: Actual policy name that will be used in the editor * definition: Actual policy using expression that will be used in the editor * check: Actual policy with check expression that will be used in the editor * command: Operation to create policy for */ export const getGeneralPolicyTemplates = (schema: string, table: string): PolicyTemplate[] => [ { id: 'policy-1', preview: false, templateName: 'Enable read access to everyone', description: 'This policy gives read access to your table for all users via the SELECT operation.', statement: ` create policy "Enable read access for all users" on "${schema}"."${table}" for select using (true);`.trim(), name: 'Enable read access for all users', definition: safeSql`true`, check: safeSql``, command: 'SELECT', roles: [], }, { id: 'policy-2', preview: false, templateName: 'Enable insert access for authenticated users only', description: 'This policy gives insert access to your table for all authenticated users only.', statement: ` create policy "Enable insert for authenticated users only" on "${schema}"."${table}" for insert to authenticated with check (true);`.trim(), name: 'Enable insert for authenticated users only', definition: safeSql``, check: safeSql`true`, command: 'INSERT', roles: ['authenticated'], }, { id: 'policy-3', preview: false, templateName: 'Enable delete access for users based on their user ID *', description: 'This policy assumes that your table has a column "user_id", and allows users to delete rows which the "user_id" column matches their ID', statement: ` create policy "Enable delete for users based on user_id" on "${schema}"."${table}" for delete using ( (select auth.uid()) = user_id );`.trim(), name: 'Enable delete for users based on user_id', definition: safeSql`(select auth.uid()) = user_id`, check: safeSql``, command: 'DELETE', roles: [], }, { id: 'policy-4', preview: false, templateName: 'Enable insert access for users based on their user ID *', description: 'This policy assumes that your table has a column "user_id", and allows users to insert rows which the "user_id" column matches their ID', statement: ` create policy "Enable insert for users based on user_id" on "${schema}"."${table}" for insert with check ( (select auth.uid()) = user_id );`.trim(), name: 'Enable insert for users based on user_id', definition: safeSql``, check: safeSql`(select auth.uid()) = user_id`, command: 'INSERT', roles: [], }, { id: 'policy-5', preview: true, name: 'Policy with table joins', templateName: 'Policy with table joins', description: ` Query across tables to build more advanced RLS rules Assuming 2 tables called \`teams\` and \`members\`, you can query both tables in the policy to control access to the members table.`, statement: ` create policy "Members can update team details if they belong to the team" on teams for update using ( (select auth.uid()) in ( select user_id from members where team_id = id ) ); `.trim(), definition: safeSql`(select auth.uid()) in (select user_id from members where team_id = id)`, check: safeSql``, command: 'UPDATE', roles: [], }, { id: 'policy-6', preview: true, templateName: 'Policy with security definer functions', description: ` Useful in a many-to-many relationship where you want to restrict access to the linking table. Assuming 2 tables called \`teams\` and \`members\`, you can use a security definer function in combination with a policy to control access to the members table.`.trim(), statement: ` create or replace function get_teams_for_user(user_id uuid) returns setof bigint as $$ select team_id from members where user_id = $1 $$ stable language sql security definer; create policy "Team members can update team members if they belong to the team" on members for all using ( team_id in (select get_teams_for_user(auth.uid())) ); `.trim(), name: 'Policy with security definer functions', definition: safeSql`team_id in (select get_teams_for_user(auth.uid()))`, check: safeSql``, command: 'ALL', roles: [], }, { id: 'policy-7', preview: true, name: 'Policy to implement Time To Live (TTL)', templateName: 'Policy to implement Time To Live (TTL)', description: ` Implement a TTL-like feature that you see in Instagram stories or Snapchat where messages expire after a day. Rows under the table are available only if they have been created within the last 24 hours.`, statement: ` create policy "Stories are live for a day" on "${schema}"."${table}" for select using ( created_at > (current_timestamp - interval '1 day') ); `.trim(), definition: safeSql`created_at > (current_timestamp - interval '1 day')`, check: safeSql``, command: 'SELECT', roles: [], }, { id: 'policy-8', preview: false, templateName: 'Allow users to only view their own data', description: 'Restrict users to reading only their own data.', statement: ` create policy "Enable users to view their own data only" on "${schema}"."${table}" for select to authenticated using ( (select auth.uid()) = user_id );`.trim(), name: 'Enable users to view their own data only', definition: safeSql`(select auth.uid()) = user_id`, check: safeSql``, command: 'SELECT', roles: ['authenticated'], }, ] export const getRealtimePolicyTemplates = (): PolicyTemplate[] => { const results = [ { id: 'policy-broadcast-1', preview: false, templateName: 'Allow listening for broadcasts for authenticated users only', description: 'This policy allows listening for broadcasts for authenticated users only.', statement: ` create policy "Allow listening for broadcasts for authenticated users only" on realtime.messages for select to authenticated using ( realtime.messages.extension = 'broadcast' );`.trim(), name: 'Allow listening for broadcasts for authenticated users only', definition: safeSql`realtime.messages.extension = 'broadcast'`, check: safeSql``, command: 'SELECT', roles: ['authenticated'], }, { id: 'policy-broadcast-2', preview: false, templateName: 'Allow pushing broadcasts for authenticated users only', description: 'This policy allows pushing broadcasts for authenticated users only.', statement: ` create policy "Allow pushing broadcasts for authenticated users only" ON realtime.messages for insert TO authenticated with check ( realtime.messages.extension = 'broadcast' );`.trim(), name: 'Allow pushing broadcasts for authenticated users only', definition: safeSql`realtime.messages.extension = 'broadcast'`, check: safeSql`realtime.messages.extension = 'broadcast'`, command: 'INSERT', roles: ['authenticated'], }, { id: 'policy-broadcast-3', preview: false, templateName: 'Allow listening for broadcasts from a specific channel', description: 'This policy allows listening for broadcasts from a specific channel.', statement: ` create policy "Allow listening for broadcasts from a specific channel" on realtime.messages for select using ( realtime.messages.extension = 'broadcast' AND realtime.topic() = 'channel_name' );`.trim(), name: 'Allow listening for broadcasts from a specific channel', definition: safeSql`realtime.messages.extension = 'broadcast' AND realtime.topic() = 'channel_name'`, check: safeSql``, command: 'SELECT', roles: [], }, { id: 'policy-broadcast-4', preview: false, templateName: 'Allow pushing broadcasts to specific channel', description: 'This policy allow pushing broadcasts to specific channel.', statement: ` create policy "Allow pushing broadcasts to specific channel" ON realtime.messages for insert with check ( realtime.messages.extension = 'broadcast' AND realtime.topic() = 'channel_name' );`.trim(), name: 'Allow pushing broadcasts to specific channel', definition: safeSql`realtime.messages.extension = 'broadcast' AND realtime.topic() = 'channel_name'`, check: safeSql`realtime.messages.extension = 'broadcast' AND realtime.topic() = 'channel_name'`, command: 'INSERT', roles: [], }, { id: 'policy-presences-1', preview: false, templateName: 'Allow listening for presences on all channels for authenticated users only', description: 'This policy enables listening for presences on all channels for all authenticated users only.', statement: ` create policy "Allow listening for presences on all channels for authenticated users only" on realtime.messages for select to authenticated using ( realtime.messages.extension = 'presence' );`.trim(), name: 'Allow listening for presences on all channels for authenticated users only', definition: safeSql`realtime.messages.extension = 'presence'`, check: safeSql``, command: 'SELECT', roles: ['authenticated'], }, { id: 'policy-presences-2', preview: false, templateName: 'Allow broadcasting presences on all channels for authenticated users only', description: 'This policy enables broadcasting presences on all channels for all authenticated users only.', statement: ` create policy "Allow broadcasting presences on all channels for authenticated users only" ON realtime.messages for insert TO authenticated with check ( realtime.messages.extension = 'presence' ); ;`.trim(), name: 'Allow broadcasting presences on all channels for authenticated users only', definition: safeSql`realtime.messages.extension = 'presence'`, check: safeSql`realtime.messages.extension = 'presence'`, command: 'INSERT', roles: ['authenticated'], }, { id: 'policy-presences-3', preview: false, templateName: 'Allow listening for presences from a specific channel', description: 'This policy enables listening for presences from a specific channel.', statement: ` create policy "Allow listening for presences from a specific channel" on realtime.messages for select using ( realtime.messages.extension = 'presence' AND realtime.topic() = 'channel_name' );`.trim(), name: 'Allow listening for presences from a specific channel', definition: safeSql`realtime.messages.extension = 'presence' AND realtime.topic() = 'channel_name'`, check: safeSql``, command: 'SELECT', roles: [], }, { id: 'policy-presences-4', preview: false, templateName: 'Publish presence to a specific channel', description: 'This policy allows publishing presence to a specific channel.', statement: ` create policy "Publish presence to a specific channel" ON realtime.messages for insert with check ( realtime.messages.extension = 'presence' AND realtime.topic() = 'channel_name' ); ;`.trim(), name: 'Publish presence to a specific channel', definition: safeSql`realtime.messages.extension = 'presence' AND realtime.topic() = 'channel_name'`, check: safeSql`realtime.messages.extension = 'presence' AND realtime.topic() = 'channel_name'`, command: 'INSERT', roles: [], }, ] as PolicyTemplate[] return results } export const getQueuePolicyTemplates = (): PolicyTemplate[] => { return [ { id: 'policy-queues-1', preview: false, templateName: 'Allow access to queue', statement: ``.trim(), name: 'Allow anon and authenticated to access messages from queue', description: 'Base policy to ensure that anon and authenticated can only access appropriate rows. USING and CHECK statements will need to be adjusted accordingly', definition: safeSql`true`, check: safeSql`true`, command: 'ALL', roles: ['anon', 'authenticated'], }, ] }