-- Create a table for public profiles
create table profiles (
id uuid references auth.users on delete cascade not null primary key,
updated_at timestamp with time zone,
username text unique,
avatar_url text,
website text,
bio text,
has_seen_onboarding boolean,
full_name text,
constraint username_length check (char_length(username) >= 3)
);
-- Set up Row Level Security (RLS)
alter table profiles
enable row level security;
create policy "Public profiles are viewable by everyone." on profiles
for select using (true);
create policy "Users can insert their own profile." on profiles
for insert with check ((select auth.uid()) = id);
create policy "Users can update own profile." on profiles
for update using ((select auth.uid()) = id);
-- Create feedback table
create table feedback (
id bigint primary key,
user_id uuid references auth.users not null,
type text,
title text,
description text,
created_at timestamp with time zone
);
-- Set up Row Level Security (RLS) for feedback table
alter table feedback
enable row level security;
-- Add policies for feedback table
create policy "Users can view their own feedback." on feedback
for select using ((select auth.uid()) = user_id);
create policy "Users can insert their own feedback." on feedback
for insert with check ((select auth.uid()) = user_id);
-- This trigger automatically creates a profile entry when a new user signs up via Supabase Auth.
create function public.handle_new_user()
returns trigger
set search_path = ''
as $$
begin
insert into public.profiles (id, full_name, avatar_url)
values (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'avatar_url');
return new;
end;
$$ language plpgsql security definer;
create trigger on_auth_user_created
after insert on auth.users
for each row execute procedure public.handle_new_user();
-- Set up Storage!
insert into storage.buckets (id, name)
values ('avatars', 'avatars');
-- Set up storage policies
CREATE POLICY "allow_avatar_reads"
ON storage.objects FOR SELECT
USING (
bucket_id = 'avatars'::text
AND auth.role() = 'authenticated'::text
);
CREATE POLICY "allow_avatar_uploads"
ON storage.objects FOR INSERT
WITH CHECK (
bucket_id = 'avatars'::text
AND auth.role() = 'authenticated'::text
AND (auth.uid())::text = (storage.foldername(name))[1]
);
CREATE POLICY "allow_avatar_updates"
ON storage.objects FOR UPDATE
USING (
bucket_id = 'avatars'::text
AND auth.role() = 'authenticated'::text
AND (auth.uid())::text = (storage.foldername(name))[1]
);
CREATE POLICY "allow_avatar_deletes"
ON storage.objects FOR DELETE
USING (
bucket_id = 'avatars'::text
AND auth.role() = 'authenticated'::text
AND (auth.uid())::text = (storage.foldername(name))[1]
);