This recipe outlines the process of creating a dedicated bucket in Supabase for avatar storage, securing the bucket, automating profile updates upon avatar picture upload and deletion, and implementing avatar management in your Bubble.io app.
It is specifically designed to work with the Supabase plugin, available here.
1. Prerequisites
This guide is the next step following our previous guide on designing and automating profile creation upon user signup, which you can retrieve here.
We assume that you have created a profiles
table
in the public schema structured as follows:
CREATE TABLE public.profiles (
id uuid not null references auth.users on delete cascade,
first_name text,
last_name text,
bio text,
avatar text,
primary key (id)
);
2. Creating a bucket for avatars storage
We will create a dedicated bucket in Supabase specifically for storing user avatars.
Each user will be assigned a unique folder, with the folder names based on the UUID
of the user to ensure a clear structure. Within each user's folder, the avatar image will be named avatar.png
.
Let's start by creating a private bucket called avatars
.
We allow only PNG files to be uploaded to this bucket.
3. Set up Row-Level Security (RLS) policies
Now, we'll implement Row Level Security (RLS) in Supabase for the avatars bucket, allowing users to manage their own avatars.
To implement our RLS policies for avatar management, we leverage the user ID (UUID) as folder names. Our policies specifically check the folder name against the authenticated user's ID, allowing users to access and update only their respective avatar folders.
You can use the SQL editor in the Supabase dashboard to implement these policies.
Allow upload
CREATE POLICY "Allow users to insert their avatar"
ON storage.objects
FOR INSERT
TO authenticated
WITH CHECK (
bucket_id = 'avatars' AND
(storage.foldername(name))[1] = auth.uid()::text
);
This policy allows authenticated users to insert their avatar
within their own folder in the avatars
bucket.
Allow update
create policy "Allow users to update their own avatar"
on storage.objects
for update
to authenticated
using (
bucket_id = 'avatars' and
(storage.foldername(name))[1] = auth.uid()::text
);
This policy allows authenticated users to update only their own avatar
within their folder in the avatars
bucket.
Allow view
create policy "Allow users to view their own avatar"
on storage.objects
for select
to authenticated
using (
bucket_id = 'avatars' and
(storage.foldername(name))[1] = auth.uid()::text
);
This policy allows authenticated users to view only their own avatar
within their folder in the avatars
bucket.
Allow delete
create policy "Allow users to delete their own avatar"
on storage.objects
for delete
to authenticated
using (
bucket_id = 'avatars' and
(storage.foldername(name))[1] = auth.uid()::text
);
This policy permits authenticated users to delete only
their own avatar within their specific folder in the avatars
bucket.
4. Automating profile update upon avatar picture upload
Whenever a user upload a picture on the avatars
bucket we
want to update the avatar
field relative to the user on the profiles
table.
To automate that, a PostgreSQL function alongside a database trigger can be used.
Function
The set_avatar_to_user
function updates the user's avatar in the
profiles table when a new file is uploaded to the avatars bucket,
and the folder in which the file is stored matches the user's ID.
CREATE OR REPLACE FUNCTION set_avatar_to_user()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.bucket_id = 'avatars' AND (storage.foldername(NEW.name))[1] = NEW.owner_id THEN
UPDATE profiles
SET avatar = NEW.name
WHERE id = NEW.owner;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Trigger
The trigger_set_avatar_to_user
is invoked after each new file upload to
storage.objects and is responsible for calling the set_avatar_to_user
function.
CREATE TRIGGER trigger_set_avatar_to_user
AFTER INSERT ON storage.objects
FOR EACH ROW
EXECUTE FUNCTION set_avatar_to_user();
In this setup, the set_avatar_to_user
function is responsible
for updating user avatars in the public.profiles table.
Meanwhile, the trigger_set_avatar_to_user
guarantees that this function
is automatically called whenever a new file is added to storage.objects,
ensuring user profiles are updated with the correct avatars.
5. Allow users to manage their avatar on Bubble.io
Now, we will enable our users to upload their profile pictures and display them in our Bubble.io app.
To implement this, you can follow these steps:
- Add an uploader component to your page.
- Add a storage component (used for creating a signed URL, as our bucket is private).
- Trigger a workflow when a file has been successfully uploaded through the uploader component.
In this workflow, we will:
- Call the
Create Signed URL
action, usingavatars
as the bucket name and the profile avatar field as the path. - Call the
Reset
action from the uploader component.
To display the avatar in your app:
- On page load, call the
Create Signed URL
action if the avatar field is not empty. - Then use the
Signed URL
field from the storage component as the source for the image.
Please note that in this example, we are displaying a default image if the user has not uploaded their own.