File size: 9,494 Bytes
3998131 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
-- ============================================================
-- SETU - Chat Persistence Schema
-- ============================================================
-- Description: Creates tables for storing chat conversations and messages
-- Author: Development Team
-- Date: 2026-01-05
-- Version: 1.0
-- ============================================================
-- Enable UUID extension (if not already enabled)
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- ============================================================
-- Table: chat_conversations
-- ============================================================
-- Stores conversation metadata for each user's chat session
-- Each conversation belongs to one user from auth.users
CREATE TABLE IF NOT EXISTS public.chat_conversations (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
title TEXT NOT NULL DEFAULT 'New Conversation',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Add comments for documentation
COMMENT ON TABLE public.chat_conversations IS 'Stores chat conversation metadata for users';
COMMENT ON COLUMN public.chat_conversations.id IS 'Unique conversation identifier';
COMMENT ON COLUMN public.chat_conversations.user_id IS 'References the user who owns this conversation (from auth.users)';
COMMENT ON COLUMN public.chat_conversations.title IS 'Conversation title, typically derived from first message';
COMMENT ON COLUMN public.chat_conversations.created_at IS 'Timestamp when conversation was created';
COMMENT ON COLUMN public.chat_conversations.updated_at IS 'Timestamp when conversation was last updated';
-- Create indexes for performance
CREATE INDEX IF NOT EXISTS idx_chat_conversations_user_id
ON public.chat_conversations(user_id);
CREATE INDEX IF NOT EXISTS idx_chat_conversations_created_at
ON public.chat_conversations(created_at DESC);
CREATE INDEX IF NOT EXISTS idx_chat_conversations_updated_at
ON public.chat_conversations(updated_at DESC);
-- ============================================================
-- Table: chat_messages
-- ============================================================
-- Stores individual messages within conversations
-- Each message belongs to one conversation
CREATE TABLE IF NOT EXISTS public.chat_messages (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
conversation_id UUID NOT NULL REFERENCES public.chat_conversations(id) ON DELETE CASCADE,
role TEXT NOT NULL CHECK (role IN ('user', 'assistant')),
content TEXT NOT NULL,
timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(),
metadata JSONB DEFAULT NULL
);
-- Add comments for documentation
COMMENT ON TABLE public.chat_messages IS 'Stores individual messages within chat conversations';
COMMENT ON COLUMN public.chat_messages.id IS 'Unique message identifier';
COMMENT ON COLUMN public.chat_messages.conversation_id IS 'References the conversation this message belongs to';
COMMENT ON COLUMN public.chat_messages.role IS 'Message sender: "user" or "assistant"';
COMMENT ON COLUMN public.chat_messages.content IS 'Message content (text)';
COMMENT ON COLUMN public.chat_messages.timestamp IS 'Timestamp when message was created';
COMMENT ON COLUMN public.chat_messages.metadata IS 'Optional JSON metadata (e.g., sources, tokens, model info)';
-- Create indexes for performance
CREATE INDEX IF NOT EXISTS idx_chat_messages_conversation_id
ON public.chat_messages(conversation_id);
CREATE INDEX IF NOT EXISTS idx_chat_messages_timestamp
ON public.chat_messages(timestamp ASC);
CREATE INDEX IF NOT EXISTS idx_chat_messages_role
ON public.chat_messages(role);
-- ============================================================
-- Function: Update updated_at timestamp automatically
-- ============================================================
-- Automatically updates the updated_at column when a conversation is modified
CREATE OR REPLACE FUNCTION public.update_conversation_updated_at()
RETURNS TRIGGER AS $$
BEGIN
UPDATE public.chat_conversations
SET updated_at = NOW()
WHERE id = NEW.conversation_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Create trigger to update conversation timestamp when new message is added
DROP TRIGGER IF EXISTS trigger_update_conversation_timestamp ON public.chat_messages;
CREATE TRIGGER trigger_update_conversation_timestamp
AFTER INSERT ON public.chat_messages
FOR EACH ROW
EXECUTE FUNCTION public.update_conversation_updated_at();
-- ============================================================
-- Row Level Security (RLS) Policies
-- ============================================================
-- Ensures users can only access their own conversations and messages
-- Enable RLS on both tables
ALTER TABLE public.chat_conversations ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.chat_messages ENABLE ROW LEVEL SECURITY;
-- Drop existing policies if they exist (for re-running migration)
DROP POLICY IF EXISTS "Users can view their own conversations" ON public.chat_conversations;
DROP POLICY IF EXISTS "Users can insert their own conversations" ON public.chat_conversations;
DROP POLICY IF EXISTS "Users can update their own conversations" ON public.chat_conversations;
DROP POLICY IF EXISTS "Users can delete their own conversations" ON public.chat_conversations;
DROP POLICY IF EXISTS "Users can view messages in their conversations" ON public.chat_messages;
DROP POLICY IF EXISTS "Users can insert messages in their conversations" ON public.chat_messages;
DROP POLICY IF EXISTS "Users can delete messages in their conversations" ON public.chat_messages;
-- Conversation Policies
CREATE POLICY "Users can view their own conversations"
ON public.chat_conversations
FOR SELECT
USING (auth.uid() = user_id);
CREATE POLICY "Users can insert their own conversations"
ON public.chat_conversations
FOR INSERT
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users can update their own conversations"
ON public.chat_conversations
FOR UPDATE
USING (auth.uid() = user_id);
CREATE POLICY "Users can delete their own conversations"
ON public.chat_conversations
FOR DELETE
USING (auth.uid() = user_id);
-- Message Policies (messages can only be accessed through owned conversations)
CREATE POLICY "Users can view messages in their conversations"
ON public.chat_messages
FOR SELECT
USING (
EXISTS (
SELECT 1 FROM public.chat_conversations
WHERE chat_conversations.id = chat_messages.conversation_id
AND chat_conversations.user_id = auth.uid()
)
);
CREATE POLICY "Users can insert messages in their conversations"
ON public.chat_messages
FOR INSERT
WITH CHECK (
EXISTS (
SELECT 1 FROM public.chat_conversations
WHERE chat_conversations.id = chat_messages.conversation_id
AND chat_conversations.user_id = auth.uid()
)
);
CREATE POLICY "Users can delete messages in their conversations"
ON public.chat_messages
FOR DELETE
USING (
EXISTS (
SELECT 1 FROM public.chat_conversations
WHERE chat_conversations.id = chat_messages.conversation_id
AND chat_conversations.user_id = auth.uid()
)
);
-- ============================================================
-- Grant permissions to authenticated users
-- ============================================================
GRANT USAGE ON SCHEMA public TO authenticated;
GRANT ALL ON public.chat_conversations TO authenticated;
GRANT ALL ON public.chat_messages TO authenticated;
-- ============================================================
-- Sample Data (Optional - Comment out if not needed)
-- ============================================================
-- Uncomment below to insert sample data for testing
-- Note: Replace 'your-user-id-here' with an actual user ID from auth.users
/*
-- Insert sample conversation
INSERT INTO public.chat_conversations (user_id, title)
VALUES ('your-user-id-here', 'Sample Legal Query');
-- Get the conversation ID (replace with actual ID after insert)
-- INSERT INTO public.chat_messages (conversation_id, role, content)
-- VALUES
-- ('conversation-id-here', 'user', 'What are my property rights in Nepal?'),
-- ('conversation-id-here', 'assistant', 'In Nepal, property rights are governed by...');
*/
-- ============================================================
-- Verification Queries (Run these to verify setup)
-- ============================================================
-- Check if tables were created
-- SELECT table_name FROM information_schema.tables
-- WHERE table_schema = 'public' AND table_name IN ('chat_conversations', 'chat_messages');
-- Check if indexes were created
-- SELECT indexname FROM pg_indexes
-- WHERE tablename IN ('chat_conversations', 'chat_messages');
-- Check if RLS is enabled
-- SELECT tablename, rowsecurity FROM pg_tables
-- WHERE schemaname = 'public' AND tablename IN ('chat_conversations', 'chat_messages');
-- ============================================================
-- Migration Complete!
-- ============================================================
-- Next Steps:
-- 1. Run this SQL in your Supabase SQL Editor
-- 2. Verify tables are created in the Table Editor
-- 3. Test with backend API routes
-- ============================================================
|