-- Enable necessary extensions create extension if not exists "uuid-ossp"; -- 1. Create journals table create table public.journals ( id uuid default uuid_generate_v4() primary key, user_id uuid references auth.users(id) on delete cascade not null, date timestamp with time zone default timezone('utc'::text, now()) not null, mood text not null, energy smallint not null, content text not null, ai_tags text[] default array[]::text[], ai_sentiment_score numeric, ai_summary text, ai_reflection text, analysis_status text default 'pending'::text, created_at timestamp with time zone default timezone('utc'::text, now()) not null, updated_at timestamp with time zone default timezone('utc'::text, now()) not null ); -- 2. Create tasks table create table public.tasks ( id uuid default uuid_generate_v4() primary key, user_id uuid references auth.users(id) on delete cascade not null, date timestamp with time zone default timezone('utc'::text, now()) not null, title text not null, description text, status text default 'todo'::text, ai_generated boolean default false, source_journal_id uuid references public.journals(id) on delete set null, created_at timestamp with time zone default timezone('utc'::text, now()) not null, updated_at timestamp with time zone default timezone('utc'::text, now()) not null ); -- 3. Create chat_sessions table create table public.chat_sessions ( id uuid default uuid_generate_v4() primary key, user_id uuid references auth.users(id) on delete cascade not null, title text not null, created_at timestamp with time zone default timezone('utc'::text, now()) not null, updated_at timestamp with time zone default timezone('utc'::text, now()) not null ); -- 4. Create chat_messages table create table public.chat_messages ( id uuid default uuid_generate_v4() primary key, session_id uuid references public.chat_sessions(id) on delete cascade not null, role text not null, content text not null, context_journal_ids uuid[] default array[]::uuid[], created_at timestamp with time zone default timezone('utc'::text, now()) not null ); -- RLS (Row Level Security) Policies alter table public.journals enable row level security; alter table public.tasks enable row level security; alter table public.chat_sessions enable row level security; alter table public.chat_messages enable row level security; -- Journals Policies create policy "Users can view their own journals." on public.journals for select using (auth.uid() = user_id); create policy "Users can insert their own journals." on public.journals for insert with check (auth.uid() = user_id); create policy "Users can update their own journals." on public.journals for update using (auth.uid() = user_id); create policy "Users can delete their own journals." on public.journals for delete using (auth.uid() = user_id); -- Tasks Policies create policy "Users can view their own tasks." on public.tasks for select using (auth.uid() = user_id); create policy "Users can insert their own tasks." on public.tasks for insert with check (auth.uid() = user_id); create policy "Users can update their own tasks." on public.tasks for update using (auth.uid() = user_id); create policy "Users can delete their own tasks." on public.tasks for delete using (auth.uid() = user_id); -- Chat Sessions Policies create policy "Users can view their own chat sessions." on public.chat_sessions for select using (auth.uid() = user_id); create policy "Users can insert their own chat sessions." on public.chat_sessions for insert with check (auth.uid() = user_id); create policy "Users can update their own chat sessions." on public.chat_sessions for update using (auth.uid() = user_id); create policy "Users can delete their own chat sessions." on public.chat_sessions for delete using (auth.uid() = user_id); -- Chat Messages Policies -- Assuming users can only access messages in their own sessions create policy "Users can view their own chat messages." on public.chat_messages for select using ( exists ( select 1 from public.chat_sessions where chat_sessions.id = chat_messages.session_id and chat_sessions.user_id = auth.uid() ) ); create policy "Users can insert their own chat messages." on public.chat_messages for insert with check ( exists ( select 1 from public.chat_sessions where chat_sessions.id = session_id and chat_sessions.user_id = auth.uid() ) ); create policy "Users can update their own chat messages." on public.chat_messages for update using ( exists ( select 1 from public.chat_sessions where chat_sessions.id = session_id and chat_sessions.user_id = auth.uid() ) ); create policy "Users can delete their own chat messages." on public.chat_messages for delete using ( exists ( select 1 from public.chat_sessions where chat_sessions.id = session_id and chat_sessions.user_id = auth.uid() ) ); -- 5. Create profiles table create table public.profiles ( id uuid references auth.users(id) on delete cascade primary key, first_name text, last_name text, avatar_url text, updated_at timestamp with time zone default timezone('utc'::text, now()) not null ); alter table public.profiles enable row level security; create policy "Users can view their own profile." on public.profiles for select using (auth.uid() = id); create policy "Users can insert their own profile." on public.profiles for insert with check (auth.uid() = id); create policy "Users can update their own profile." on public.profiles for update using (auth.uid() = id); -- Function to handle new user signup create or replace function public.handle_new_user() returns trigger as $$$ begin insert into public.profiles (id, first_name, last_name, avatar_url) values (new.id, '', '', ''); return new; end; $$$ language plpgsql security definer; -- Drop trigger if exists to avoid errors on multiple runs drop trigger if exists on_auth_user_created on auth.users; -- Trigger to automatically create profile on signup create trigger on_auth_user_created after insert on auth.users for each row execute procedure public.handle_new_user(); -- Setup storage bucket for avatars insert into storage.buckets (id, name, public) values ('avatars', 'avatars', true) on conflict (id) do nothing; create policy "Avatar images are publicly accessible." on storage.objects for select using ( bucket_id = 'avatars' ); create policy "Users can upload an avatar." on storage.objects for insert with check ( bucket_id = 'avatars' AND auth.uid()::text = (storage.foldername(name))[1] ); create policy "Users can update their own avatar." on storage.objects for update using ( bucket_id = 'avatars' AND auth.uid()::text = (storage.foldername(name))[1] ); create policy "Users can delete their own avatar." on storage.objects for delete using ( bucket_id = 'avatars' AND auth.uid()::text = (storage.foldername(name))[1] );