पाठ 13 / 25

Storage Buckets and Policies

Public files, private files and signed URLs.

Buckets backed by Postgres metadata

Files live in buckets. A public bucket serves files to anyone through a permanent URL; a private bucket requires authorisation, either a user JWT or a time-limited signed URL. Object metadata is stored in the storage.objects table, so access is controlled with ordinary RLS policies on that table. A common convention is to put each user's files under a folder named after their user id and check it with storage.foldername(name).

Files and live updates

Storage keeps files in buckets guarded by policies; Realtime pushes changes and messages to connected clients.

Three ideas: buckets and access, realtime channels, choosing the right tool.
Figure 5.1 — Upload, bucket policy, subscribers receiving events.

Upload, signed URL and a folder policy

supabase-js plus SQL.

// upload into the user's own folder of a private bucket
const path = `${user.id}/avatar.png`
await supabase.storage.from('avatars').upload(path, file, { upsert: true })

// a link that expires after 60 seconds
const { data } = await supabase.storage.from('avatars').createSignedUrl(path, 60)

// public buckets instead use a permanent URL:
// supabase.storage.from('public-assets').getPublicUrl('logo.png')

/* SQL policy on storage.objects:
create policy "users upload to own folder" on storage.objects
  for insert to authenticated
  with check (
    bucket_id = 'avatars'
    and (storage.foldername(name))[1] = (select auth.uid())::text
  );
*/

Default to private buckets

Make a bucket public only for truly public assets such as logos. Everything user-related should be private with policies or signed URLs.

त्वरित जाँच: How do you share a file from a private bucket for a short time?

  • Make the bucket public temporarily
  • Create a signed URL with an expiry
  • Send the service_role key to the user
  • Disable RLS on storage.objects
Answer

Create a signed URL with an expiry — Signed URLs grant time-limited access.