Andrew-dev1.1 / supabase /schema.sql
truegleai
Add full project files
2376451
raw
history blame
6.43 kB
-- Supabase Database Schema
-- Run this SQL in your Supabase SQL Editor
-- Enable UUID extension
create extension if not exists "uuid-ossp";
-- User profiles table
create table if not exists profiles (
id uuid references auth.users on delete cascade primary key,
email text unique,
full_name text,
avatar_url text,
is_premium boolean default true, -- Beta: all users premium
premium_expires_at timestamp with time zone,
tokens_remaining integer default -1, -- Beta: unlimited
tokens_reset_at timestamp with time zone default now() + interval '24 hours',
created_at timestamp with time zone default now(),
updated_at timestamp with time zone default now()
);
-- Projects table (user saved code)
create table if not exists projects (
id uuid default uuid_generate_v4() primary key,
user_id uuid references profiles(id) on delete cascade not null,
name text default 'Untitled Project',
description text,
html_code text default '',
css_code text default '',
js_code text default '',
preview_url text,
thumbnail_url text,
is_public boolean default false,
created_at timestamp with time zone default now(),
updated_at timestamp with time zone default now()
);
-- AI chat messages history
create table if not exists chat_messages (
id uuid default uuid_generate_v4() primary key,
user_id uuid references profiles(id) on delete cascade not null,
project_id uuid references projects(id) on delete cascade,
role text not null check (role in ('user', 'assistant')),
content text not null,
tokens_used integer default 0,
created_at timestamp with time zone default now()
);
-- Token transactions ledger
create table if not exists token_transactions (
id uuid default uuid_generate_v4() primary key,
user_id uuid references profiles(id) on delete cascade not null,
transaction_type text not null check (transaction_type in ('ai_usage', 'ad_reward', 'daily_reset', 'purchase', 'premium_bonus')),
amount integer not null,
description text,
created_at timestamp with time zone default now()
);
-- Subscriptions table (kept for future Stripe integration)
create table if not exists subscriptions (
id uuid default uuid_generate_v4() primary key,
user_id uuid references profiles(id) on delete cascade unique not null,
status text not null check (status in ('active', 'canceled', 'past_due', 'trialing', 'beta')),
current_period_end timestamp with time zone,
cancel_at_period_end boolean default false,
created_at timestamp with time zone default now(),
updated_at timestamp with time zone default now()
);
-- Ad engagement tracking
create table if not exists ad_engagements (
id uuid default uuid_generate_v4() primary key,
user_id uuid references profiles(id) on delete cascade not null,
ad_type text not null check (ad_type in ('banner', 'rewarded')),
ad_slot text,
reward_amount integer default 0,
completed boolean default false,
created_at timestamp with time zone default now()
);
-- Enable Row Level Security
alter table profiles enable row level security;
alter table projects enable row level security;
alter table chat_messages enable row level security;
alter table token_transactions enable row level security;
alter table subscriptions enable row level security;
alter table ad_engagements enable row level security;
-- RLS Policies for profiles
create policy "Users can view own profile"
on profiles for select
using (auth.uid() = id);
create policy "Users can update own profile"
on profiles for update
using (auth.uid() = id);
-- RLS Policies for projects
create policy "Users can view own projects"
on projects for select
using (auth.uid() = user_id);
create policy "Users can view public projects"
on projects for select
using (is_public = true);
create policy "Users can create projects"
on projects for insert
with check (auth.uid() = user_id);
create policy "Users can update own projects"
on projects for update
using (auth.uid() = user_id);
create policy "Users can delete own projects"
on projects for delete
using (auth.uid() = user_id);
-- RLS Policies for chat_messages
create policy "Users can view own messages"
on chat_messages for select
using (auth.uid() = user_id);
create policy "Users can create messages"
on chat_messages for insert
with check (auth.uid() = user_id);
-- RLS Policies for token_transactions
create policy "Users can view own transactions"
on token_transactions for select
using (auth.uid() = user_id);
create policy "System can create transactions"
on token_transactions for insert
with check (true);
-- RLS Policies for subscriptions
create policy "Users can view own subscription"
on subscriptions for select
using (auth.uid() = user_id);
create policy "Users can manage own subscriptions"
on subscriptions for all
using (auth.uid() = user_id);
-- RLS Policies for ad_engagements
create policy "Users can view own engagements"
on ad_engagements for select
using (auth.uid() = user_id);
create policy "System can create engagements"
on ad_engagements for insert
with check (true);
-- Function to handle new user creation
create or replace function public.handle_new_user()
returns trigger as $$
begin
insert into public.profiles (id, email, full_name, avatar_url)
values (
new.id,
new.email,
new.raw_user_meta_data->>'full_name',
new.raw_user_meta_data->>'avatar_url'
);
return new;
end;
$$ language plpgsql security definer;
-- Trigger for new user creation
create or replace trigger on_auth_user_created
after insert on auth.users
for each row execute procedure public.handle_new_user();
-- Function to reset tokens daily
create or replace function reset_daily_tokens()
returns void as $$
begin
update profiles
set tokens_remaining = 50,
tokens_reset_at = now() + interval '24 hours'
where tokens_reset_at <= now()
and is_premium = false;
end;
$$ language plpgsql security definer;
-- Indexes for performance
create index if not exists idx_projects_user_id on projects(user_id);
create index if not exists idx_projects_updated on projects(user_id, updated_at desc);
create index if not exists idx_chat_messages_user_project on chat_messages(user_id, project_id);
create index if not exists idx_token_transactions_user on token_transactions(user_id, created_at desc);
create index if not exists idx_ad_engagements_user on ad_engagements(user_id, created_at desc);