Supabase: How To Get User Profile Data?
Supabase: How to Get User Profile Data?
Alright guys, let’s dive into how you can snag user profile data using Supabase. If you’re building an app with Supabase, you’ll quickly realize that getting user info is super important. It lets you personalize the experience, manage access, and do a whole bunch of other cool stuff. This guide will walk you through the steps, sprinkling in some tips and tricks along the way to make your life easier.
Table of Contents
Setting Up Your Supabase Project
Before we get into the code, make sure you have a Supabase project up and running. If you don’t, head over to the Supabase website and create a new project. It’s pretty straightforward: just sign up, create a new project, and grab your API keys. You’ll need these keys to connect your app to your Supabase backend. Once you have your project set up, you’ll also want to create a table to store your user profiles. This table will hold all the extra information about your users that isn’t included in the default authentication data. Think of things like usernames, avatars, bios, and anything else that makes your app unique. To create the table, go to your Supabase dashboard, navigate to the SQL editor, and run a
CREATE TABLE
statement. Here’s an example:
CREATE TABLE profiles (
id UUID PRIMARY KEY REFERENCES auth.users(id),
username VARCHAR(255) UNIQUE NOT NULL,
full_name VARCHAR(255),
avatar_url TEXT,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now())
);
This SQL script creates a table named
profiles
with columns for
id
,
username
,
full_name
, and
avatar_url
. The
id
column is a foreign key that references the
auth.users
table, which is where Supabase stores the default user authentication data. This ensures that each profile is linked to a specific user. The
username
column is set to be unique and not null, ensuring that each user has a unique username. The
updated_at
column is a timestamp that automatically updates whenever the row is modified. Once you’ve created the table, you’ll also want to set up row-level security (RLS) policies to control who can access and modify the data. This is crucial for ensuring that users can only access their own profile data. To do this, go to the Authentication section in your Supabase dashboard and enable RLS for the
profiles
table. Then, create a policy that allows users to select, insert, update, and delete their own profile data. Here’s an example policy:
CREATE POLICY "Enable read access for users based on user_id" ON profiles
AS PERMISSIVE FOR SELECT
TO authenticated
USING (auth.uid() = id);
CREATE POLICY "Enable insert for authenticated users only" ON profiles
AS PERMISSIVE FOR INSERT
TO authenticated
WITH CHECK (auth.uid() = id);
CREATE POLICY "Enable update for users based on user_id" ON profiles
AS PERMISSIVE FOR UPDATE
TO authenticated
USING (auth.uid() = id);
CREATE POLICY "Enable delete for users based on user_id" ON profiles
AS PERMISSIVE FOR DELETE
TO authenticated
USING (auth.uid() = id);
These policies ensure that only authenticated users can access the
profiles
table and that they can only modify their own profile data. The
auth.uid()
function returns the ID of the currently authenticated user, and the
USING
and
WITH CHECK
clauses ensure that the user can only access or modify rows where the
id
column matches their user ID.
Fetching User Profile Data
Now that you’ve set up your Supabase project and created the
profiles
table, let’s get into the code for fetching user profile data. You’ll typically want to do this after a user logs in or when you need to display their profile information. The basic idea is to use the Supabase client library to query the
profiles
table and retrieve the row that matches the currently authenticated user’s ID. Here’s how you can do it in JavaScript:
import { createClient } from '@supabase/supabase-js';
const supabaseUrl = 'YOUR_SUPABASE_URL';
const supabaseKey = 'YOUR_SUPABASE_ANON_KEY';
const supabase = createClient(supabaseUrl, supabaseKey);
async function getProfile() {
const { data: profile, error } = await supabase
.from('profiles')
.select('*')
.eq('id', supabase.auth.currentUser.id)
.single();
if (error) {
console.error('Error fetching profile:', error);
return null;
}
return profile;
}
// Example usage:
getProfile().then(profile => {
if (profile) {
console.log('User profile:', profile);
} else {
console.log('No profile found for this user.');
}
});
In this code, we first create a Supabase client using your project URL and API key. Then, we define an async function called
getProfile
that queries the
profiles
table. We use the
select('*')
method to retrieve all columns from the table. The
eq('id', supabase.auth.currentUser.id)
method filters the results to only return the row where the
id
column matches the currently authenticated user’s ID. The
single()
method ensures that we only return a single row, which is what we expect since the
id
column is a primary key. If there’s an error, we log it to the console and return
null
. Otherwise, we return the profile data. To use this function, you can call it and then log the profile data to the console. You can also use the profile data to update your UI or perform other actions.
Handling Updates and Inserts
Fetching user profile data is just the beginning. You’ll also need to handle updates and inserts when users modify their profile information or create a new profile. The process is similar to fetching data, but you’ll use the
update
and
insert
methods instead of the
select
method. Here’s how you can update a user’s profile:
async function updateProfile(updates) {
const { data, error } = await supabase
.from('profiles')
.update(updates)
.eq('id', supabase.auth.currentUser.id)
if (error) {
console.error('Error updating profile:', error);
return false;
}
return true;
}
// Example usage:
updateProfile({ username: 'newusername', full_name: 'New Name' }).then(success => {
if (success) {
console.log('Profile updated successfully!');
} else {
console.log('Failed to update profile.');
}
});
In this code, we define an async function called
updateProfile
that takes an object containing the updates to apply to the user’s profile. We use the
update(updates)
method to update the row in the
profiles
table that matches the currently authenticated user’s ID. The
eq('id', supabase.auth.currentUser.id)
method ensures that we only update the row for the current user. If there’s an error, we log it to the console and return
false
. Otherwise, we return
true
. To use this function, you can call it with an object containing the updates you want to apply. For example, you can update the user’s username and full name by passing in an object like
{ username: 'newusername', full_name: 'New Name' }
. If a user doesn’t have a profile yet, you’ll need to insert a new row into the
profiles
table. Here’s how you can do it:
async function createProfile(profileData) {
const { data, error } = await supabase
.from('profiles')
.insert([{
id: supabase.auth.currentUser.id,
...profileData
}]);
if (error) {
console.error('Error creating profile:', error);
return false;
}
return true;
}
// Example usage:
createProfile({ username: 'newusername', full_name: 'New Name' }).then(success => {
if (success) {
console.log('Profile created successfully!');
} else {
console.log('Failed to create profile.');
}
});
In this code, we define an async function called
createProfile
that takes an object containing the data for the new profile. We use the
insert
method to insert a new row into the
profiles
table. We pass in an array containing a single object with the data for the new profile. The
id
column is set to the currently authenticated user’s ID, and the other columns are set to the values in the
profileData
object. If there’s an error, we log it to the console and return
false
. Otherwise, we return
true
. To use this function, you can call it with an object containing the data for the new profile. For example, you can create a new profile with a username and full name by passing in an object like
{ username: 'newusername', full_name: 'New Name' }
.
Real-time Updates
One of the coolest features of Supabase is its real-time capabilities. You can subscribe to changes in your
profiles
table and automatically update your UI whenever a user’s profile is updated. This is great for building collaborative apps or displaying live updates to your users. Here’s how you can set up a real-time subscription:
supabase
.from('profiles')
.on('UPDATE', payload => {
console.log('Change received!', payload)
// Update your UI with the new profile data
})
.eq('id', supabase.auth.currentUser.id)
.subscribe()
In this code, we use the
from
method to specify the
profiles
table. We then use the
on
method to subscribe to
UPDATE
events. This means that whenever a row in the
profiles
table is updated, the callback function will be called. The
payload
object contains the new and old data for the updated row. We use the
eq('id', supabase.auth.currentUser.id)
method to filter the events to only receive updates for the currently authenticated user’s profile. Finally, we call the
subscribe
method to start the subscription. To unsubscribe from the events, you can call the
unsubscribe
method on the subscription object. This will stop the callback function from being called when the row is updated.
Best Practices and Security Tips
Before we wrap up, here are a few best practices and security tips to keep in mind when working with user profile data in Supabase:
-
Use Row-Level Security (RLS):
As mentioned earlier, RLS is crucial for ensuring that users can only access their own profile data. Make sure you have RLS enabled for your
profilestable and that you have policies in place to control who can access and modify the data. - Validate User Input: Always validate user input on the client-side and server-side to prevent malicious data from being stored in your database. This includes checking the length of strings, validating email addresses, and sanitizing any HTML or JavaScript code.
- Use HTTPS: Make sure your app is using HTTPS to encrypt all traffic between the client and the server. This will prevent eavesdropping and ensure that sensitive data like passwords and API keys are protected.
- Store Passwords Securely: Never store passwords in plain text. Always use a secure hashing algorithm like bcrypt or Argon2 to hash passwords before storing them in your database. Supabase Auth handles this for you automatically, so you don’t have to worry about it.
- Regularly Update Your Dependencies: Make sure you’re using the latest versions of the Supabase client library and any other dependencies in your project. This will ensure that you have the latest security patches and bug fixes.
Conclusion
So there you have it! Getting user profile data with Supabase is pretty straightforward once you get the hang of it. Just remember to set up your project correctly, create your
profiles
table, and use the Supabase client library to fetch, update, and insert data. And don’t forget to use RLS to keep your data secure. With these tips, you’ll be building awesome, personalized apps in no time. Happy coding!