PolicyEditorModal.constants.ts329 lines · main
| 1 | import { safeSql } from '@supabase/pg-meta/src/pg-format' |
| 2 | |
| 3 | import { PolicyTemplate } from '../PolicyTemplates/PolicyTemplates.constants' |
| 4 | |
| 5 | /** |
| 6 | * ---------------------------------------------------------------- |
| 7 | * PostgreSQL policy templates for the auth policies page |
| 8 | * ---------------------------------------------------------------- |
| 9 | * id: Unique identifier for the monaco editor to dynamically refresh |
| 10 | * templateName: As a display for a more descriptive title for the policy |
| 11 | * description: Additional details about the template and how to make it yours |
| 12 | * statement: SQL statement template for the policy |
| 13 | * |
| 14 | * name: Actual policy name that will be used in the editor |
| 15 | * definition: Actual policy using expression that will be used in the editor |
| 16 | * check: Actual policy with check expression that will be used in the editor |
| 17 | * command: Operation to create policy for |
| 18 | */ |
| 19 | |
| 20 | export const getGeneralPolicyTemplates = (schema: string, table: string): PolicyTemplate[] => [ |
| 21 | { |
| 22 | id: 'policy-1', |
| 23 | preview: false, |
| 24 | templateName: 'Enable read access to everyone', |
| 25 | description: |
| 26 | 'This policy gives read access to your table for all users via the SELECT operation.', |
| 27 | statement: ` |
| 28 | create policy "Enable read access for all users" |
| 29 | on "${schema}"."${table}" |
| 30 | for select using (true);`.trim(), |
| 31 | name: 'Enable read access for all users', |
| 32 | definition: safeSql`true`, |
| 33 | check: safeSql``, |
| 34 | command: 'SELECT', |
| 35 | roles: [], |
| 36 | }, |
| 37 | { |
| 38 | id: 'policy-2', |
| 39 | preview: false, |
| 40 | templateName: 'Enable insert access for authenticated users only', |
| 41 | description: 'This policy gives insert access to your table for all authenticated users only.', |
| 42 | statement: ` |
| 43 | create policy "Enable insert for authenticated users only" |
| 44 | on "${schema}"."${table}" |
| 45 | for insert to authenticated |
| 46 | with check (true);`.trim(), |
| 47 | name: 'Enable insert for authenticated users only', |
| 48 | definition: safeSql``, |
| 49 | check: safeSql`true`, |
| 50 | command: 'INSERT', |
| 51 | roles: ['authenticated'], |
| 52 | }, |
| 53 | { |
| 54 | id: 'policy-3', |
| 55 | preview: false, |
| 56 | templateName: 'Enable delete access for users based on their user ID *', |
| 57 | description: |
| 58 | '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', |
| 59 | statement: ` |
| 60 | create policy "Enable delete for users based on user_id" |
| 61 | on "${schema}"."${table}" |
| 62 | for delete using ( |
| 63 | (select auth.uid()) = user_id |
| 64 | );`.trim(), |
| 65 | name: 'Enable delete for users based on user_id', |
| 66 | definition: safeSql`(select auth.uid()) = user_id`, |
| 67 | check: safeSql``, |
| 68 | command: 'DELETE', |
| 69 | roles: [], |
| 70 | }, |
| 71 | { |
| 72 | id: 'policy-4', |
| 73 | preview: false, |
| 74 | templateName: 'Enable insert access for users based on their user ID *', |
| 75 | description: |
| 76 | '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', |
| 77 | statement: ` |
| 78 | create policy "Enable insert for users based on user_id" |
| 79 | on "${schema}"."${table}" |
| 80 | for insert with check ( |
| 81 | (select auth.uid()) = user_id |
| 82 | );`.trim(), |
| 83 | name: 'Enable insert for users based on user_id', |
| 84 | definition: safeSql``, |
| 85 | check: safeSql`(select auth.uid()) = user_id`, |
| 86 | command: 'INSERT', |
| 87 | roles: [], |
| 88 | }, |
| 89 | { |
| 90 | id: 'policy-5', |
| 91 | preview: true, |
| 92 | name: 'Policy with table joins', |
| 93 | templateName: 'Policy with table joins', |
| 94 | description: ` |
| 95 | Query across tables to build more advanced RLS rules |
| 96 | |
| 97 | Assuming 2 tables called \`teams\` and \`members\`, you can query both tables in the policy to control access to the members table.`, |
| 98 | statement: ` |
| 99 | create policy "Members can update team details if they belong to the team" |
| 100 | on teams for update using ( |
| 101 | (select auth.uid()) in ( |
| 102 | select user_id from members where team_id = id |
| 103 | ) |
| 104 | ); |
| 105 | `.trim(), |
| 106 | definition: safeSql`(select auth.uid()) in (select user_id from members where team_id = id)`, |
| 107 | check: safeSql``, |
| 108 | command: 'UPDATE', |
| 109 | roles: [], |
| 110 | }, |
| 111 | { |
| 112 | id: 'policy-6', |
| 113 | preview: true, |
| 114 | templateName: 'Policy with security definer functions', |
| 115 | description: ` |
| 116 | Useful in a many-to-many relationship where you want to restrict access to the linking table. |
| 117 | |
| 118 | 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(), |
| 119 | statement: ` |
| 120 | create or replace function get_teams_for_user(user_id uuid) |
| 121 | returns setof bigint as $$ |
| 122 | select team_id from members where user_id = $1 |
| 123 | $$ stable language sql security definer; |
| 124 | |
| 125 | create policy "Team members can update team members if they belong to the team" |
| 126 | on members |
| 127 | for all using ( |
| 128 | team_id in (select get_teams_for_user(auth.uid())) |
| 129 | ); |
| 130 | `.trim(), |
| 131 | name: 'Policy with security definer functions', |
| 132 | definition: safeSql`team_id in (select get_teams_for_user(auth.uid()))`, |
| 133 | check: safeSql``, |
| 134 | command: 'ALL', |
| 135 | roles: [], |
| 136 | }, |
| 137 | { |
| 138 | id: 'policy-7', |
| 139 | preview: true, |
| 140 | name: 'Policy to implement Time To Live (TTL)', |
| 141 | templateName: 'Policy to implement Time To Live (TTL)', |
| 142 | description: ` |
| 143 | Implement a TTL-like feature that you see in Instagram stories or Snapchat where messages expire after a day. |
| 144 | |
| 145 | Rows under the table are available only if they have been created within the last 24 hours.`, |
| 146 | statement: ` |
| 147 | create policy "Stories are live for a day" |
| 148 | on "${schema}"."${table}" |
| 149 | for select using ( |
| 150 | created_at > (current_timestamp - interval '1 day') |
| 151 | ); |
| 152 | `.trim(), |
| 153 | definition: safeSql`created_at > (current_timestamp - interval '1 day')`, |
| 154 | check: safeSql``, |
| 155 | command: 'SELECT', |
| 156 | roles: [], |
| 157 | }, |
| 158 | { |
| 159 | id: 'policy-8', |
| 160 | preview: false, |
| 161 | templateName: 'Allow users to only view their own data', |
| 162 | description: 'Restrict users to reading only their own data.', |
| 163 | statement: ` |
| 164 | create policy "Enable users to view their own data only" |
| 165 | on "${schema}"."${table}" |
| 166 | for select |
| 167 | to authenticated |
| 168 | using ( |
| 169 | (select auth.uid()) = user_id |
| 170 | );`.trim(), |
| 171 | name: 'Enable users to view their own data only', |
| 172 | definition: safeSql`(select auth.uid()) = user_id`, |
| 173 | check: safeSql``, |
| 174 | command: 'SELECT', |
| 175 | roles: ['authenticated'], |
| 176 | }, |
| 177 | ] |
| 178 | |
| 179 | export const getRealtimePolicyTemplates = (): PolicyTemplate[] => { |
| 180 | const results = [ |
| 181 | { |
| 182 | id: 'policy-broadcast-1', |
| 183 | preview: false, |
| 184 | templateName: 'Allow listening for broadcasts for authenticated users only', |
| 185 | description: 'This policy allows listening for broadcasts for authenticated users only.', |
| 186 | statement: ` |
| 187 | create policy "Allow listening for broadcasts for authenticated users only" |
| 188 | on realtime.messages for select |
| 189 | to authenticated |
| 190 | using ( realtime.messages.extension = 'broadcast' );`.trim(), |
| 191 | name: 'Allow listening for broadcasts for authenticated users only', |
| 192 | definition: safeSql`realtime.messages.extension = 'broadcast'`, |
| 193 | check: safeSql``, |
| 194 | command: 'SELECT', |
| 195 | roles: ['authenticated'], |
| 196 | }, |
| 197 | { |
| 198 | id: 'policy-broadcast-2', |
| 199 | preview: false, |
| 200 | templateName: 'Allow pushing broadcasts for authenticated users only', |
| 201 | description: 'This policy allows pushing broadcasts for authenticated users only.', |
| 202 | statement: ` |
| 203 | create policy "Allow pushing broadcasts for authenticated users only" |
| 204 | ON realtime.messages for insert |
| 205 | TO authenticated |
| 206 | with check ( realtime.messages.extension = 'broadcast' );`.trim(), |
| 207 | name: 'Allow pushing broadcasts for authenticated users only', |
| 208 | definition: safeSql`realtime.messages.extension = 'broadcast'`, |
| 209 | check: safeSql`realtime.messages.extension = 'broadcast'`, |
| 210 | command: 'INSERT', |
| 211 | roles: ['authenticated'], |
| 212 | }, |
| 213 | { |
| 214 | id: 'policy-broadcast-3', |
| 215 | preview: false, |
| 216 | templateName: 'Allow listening for broadcasts from a specific channel', |
| 217 | description: 'This policy allows listening for broadcasts from a specific channel.', |
| 218 | statement: ` |
| 219 | create policy "Allow listening for broadcasts from a specific channel" |
| 220 | on realtime.messages for select |
| 221 | using ( realtime.messages.extension = 'broadcast' AND realtime.topic() = 'channel_name' );`.trim(), |
| 222 | name: 'Allow listening for broadcasts from a specific channel', |
| 223 | definition: safeSql`realtime.messages.extension = 'broadcast' AND realtime.topic() = 'channel_name'`, |
| 224 | check: safeSql``, |
| 225 | command: 'SELECT', |
| 226 | roles: [], |
| 227 | }, |
| 228 | { |
| 229 | id: 'policy-broadcast-4', |
| 230 | preview: false, |
| 231 | templateName: 'Allow pushing broadcasts to specific channel', |
| 232 | description: 'This policy allow pushing broadcasts to specific channel.', |
| 233 | statement: ` |
| 234 | create policy "Allow pushing broadcasts to specific channel" |
| 235 | ON realtime.messages for insert |
| 236 | with check ( realtime.messages.extension = 'broadcast' AND realtime.topic() = 'channel_name' );`.trim(), |
| 237 | name: 'Allow pushing broadcasts to specific channel', |
| 238 | definition: safeSql`realtime.messages.extension = 'broadcast' AND realtime.topic() = 'channel_name'`, |
| 239 | check: safeSql`realtime.messages.extension = 'broadcast' AND realtime.topic() = 'channel_name'`, |
| 240 | command: 'INSERT', |
| 241 | roles: [], |
| 242 | }, |
| 243 | { |
| 244 | id: 'policy-presences-1', |
| 245 | preview: false, |
| 246 | templateName: 'Allow listening for presences on all channels for authenticated users only', |
| 247 | description: |
| 248 | 'This policy enables listening for presences on all channels for all authenticated users only.', |
| 249 | statement: ` |
| 250 | create policy "Allow listening for presences on all channels for authenticated users only" |
| 251 | on realtime.messages for select |
| 252 | to authenticated |
| 253 | using ( realtime.messages.extension = 'presence' );`.trim(), |
| 254 | name: 'Allow listening for presences on all channels for authenticated users only', |
| 255 | definition: safeSql`realtime.messages.extension = 'presence'`, |
| 256 | check: safeSql``, |
| 257 | command: 'SELECT', |
| 258 | roles: ['authenticated'], |
| 259 | }, |
| 260 | { |
| 261 | id: 'policy-presences-2', |
| 262 | preview: false, |
| 263 | templateName: 'Allow broadcasting presences on all channels for authenticated users only', |
| 264 | description: |
| 265 | 'This policy enables broadcasting presences on all channels for all authenticated users only.', |
| 266 | statement: ` |
| 267 | create policy "Allow broadcasting presences on all channels for authenticated users only" |
| 268 | ON realtime.messages for insert |
| 269 | TO authenticated |
| 270 | with check ( realtime.messages.extension = 'presence' ); |
| 271 | ;`.trim(), |
| 272 | name: 'Allow broadcasting presences on all channels for authenticated users only', |
| 273 | definition: safeSql`realtime.messages.extension = 'presence'`, |
| 274 | check: safeSql`realtime.messages.extension = 'presence'`, |
| 275 | command: 'INSERT', |
| 276 | roles: ['authenticated'], |
| 277 | }, |
| 278 | { |
| 279 | id: 'policy-presences-3', |
| 280 | preview: false, |
| 281 | templateName: 'Allow listening for presences from a specific channel', |
| 282 | description: 'This policy enables listening for presences from a specific channel.', |
| 283 | statement: ` |
| 284 | create policy "Allow listening for presences from a specific channel" |
| 285 | on realtime.messages for select |
| 286 | using ( realtime.messages.extension = 'presence' AND realtime.topic() = 'channel_name' );`.trim(), |
| 287 | name: 'Allow listening for presences from a specific channel', |
| 288 | definition: safeSql`realtime.messages.extension = 'presence' AND realtime.topic() = 'channel_name'`, |
| 289 | check: safeSql``, |
| 290 | command: 'SELECT', |
| 291 | roles: [], |
| 292 | }, |
| 293 | { |
| 294 | id: 'policy-presences-4', |
| 295 | preview: false, |
| 296 | templateName: 'Publish presence to a specific channel', |
| 297 | description: 'This policy allows publishing presence to a specific channel.', |
| 298 | statement: ` |
| 299 | create policy "Publish presence to a specific channel" |
| 300 | ON realtime.messages for insert |
| 301 | with check ( realtime.messages.extension = 'presence' AND realtime.topic() = 'channel_name' ); |
| 302 | ;`.trim(), |
| 303 | name: 'Publish presence to a specific channel', |
| 304 | definition: safeSql`realtime.messages.extension = 'presence' AND realtime.topic() = 'channel_name'`, |
| 305 | check: safeSql`realtime.messages.extension = 'presence' AND realtime.topic() = 'channel_name'`, |
| 306 | command: 'INSERT', |
| 307 | roles: [], |
| 308 | }, |
| 309 | ] as PolicyTemplate[] |
| 310 | return results |
| 311 | } |
| 312 | |
| 313 | export const getQueuePolicyTemplates = (): PolicyTemplate[] => { |
| 314 | return [ |
| 315 | { |
| 316 | id: 'policy-queues-1', |
| 317 | preview: false, |
| 318 | templateName: 'Allow access to queue', |
| 319 | statement: ``.trim(), |
| 320 | name: 'Allow anon and authenticated to access messages from queue', |
| 321 | description: |
| 322 | 'Base policy to ensure that anon and authenticated can only access appropriate rows. USING and CHECK statements will need to be adjusted accordingly', |
| 323 | definition: safeSql`true`, |
| 324 | check: safeSql`true`, |
| 325 | command: 'ALL', |
| 326 | roles: ['anon', 'authenticated'], |
| 327 | }, |
| 328 | ] |
| 329 | } |