Try our new Bubble.io plugin, Supabase!

Get Started

Managing avatars on Bubble.io with Supabase

10 december 2023 · 10 minutes read

Manage your user's avatars on Bubble.io with Supabase

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.

Create avatars 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.

Avatar management

To implement this, you can follow these steps:

  1. Add an uploader component to your page.
  2. Add a storage component (used for creating a signed URL, as our bucket is private).
  3. 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, using avatars as the bucket name and the profile avatar field as the path.
  • Call the Reset action from the uploader component.
Uploading avatar

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.


Do you have any questions or feedback? Feel free to reach out – we would love to hear from you!