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:sqlCREATE 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
sqlCREATE 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
sqlcreate 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
sqlcreate 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
sqlcreate 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.sqlCREATE 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.sqlCREATE 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.