mirror of
http://88.130.71.182:3000/BlitTech/contexta_be.git
synced 2026-06-12 23:23:21 +00:00
Initial commit
This commit is contained in:
192
supabase_schema.sql
Normal file
192
supabase_schema.sql
Normal file
@@ -0,0 +1,192 @@
|
||||
-- ============================================================
|
||||
-- CONTEXTA - Supabase Database Schema
|
||||
-- Run this in your Supabase SQL Editor
|
||||
-- ============================================================
|
||||
|
||||
-- Enable UUID extension
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
|
||||
-- ─── Companies ────────────────────────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS companies (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
owner_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
website VARCHAR(255),
|
||||
industry VARCHAR(100),
|
||||
logo_url TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ─── Subscriptions ────────────────────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS subscriptions (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE UNIQUE,
|
||||
plan VARCHAR(50) DEFAULT 'free',
|
||||
status VARCHAR(50) DEFAULT 'active',
|
||||
stripe_customer_id VARCHAR(255) UNIQUE,
|
||||
stripe_subscription_id VARCHAR(255),
|
||||
stripe_price_id VARCHAR(255),
|
||||
current_period_start TIMESTAMPTZ,
|
||||
current_period_end TIMESTAMPTZ,
|
||||
chatbots_published INT DEFAULT 0,
|
||||
conversations_used INT DEFAULT 0,
|
||||
trial_end TIMESTAMPTZ,
|
||||
canceled_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ─── Chatbots ─────────────────────────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS chatbots (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
company_id UUID REFERENCES companies(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
system_prompt TEXT,
|
||||
model VARCHAR(200) DEFAULT 'accounts/fireworks/models/llama-v3p1-70b-instruct',
|
||||
temperature DECIMAL(3,2) DEFAULT 0.70,
|
||||
max_tokens INT DEFAULT 1000,
|
||||
primary_color VARCHAR(20) DEFAULT '#6366f1',
|
||||
welcome_message TEXT DEFAULT 'Hello! How can I help you today?',
|
||||
category VARCHAR(100),
|
||||
industry VARCHAR(100),
|
||||
languages JSONB DEFAULT '["en"]',
|
||||
visibility VARCHAR(50) DEFAULT 'preview',
|
||||
is_published BOOLEAN DEFAULT FALSE,
|
||||
qdrant_collection_name VARCHAR(255) UNIQUE,
|
||||
average_rating DECIMAL(3,1),
|
||||
total_conversations INT DEFAULT 0,
|
||||
is_featured BOOLEAN DEFAULT FALSE,
|
||||
published_at TIMESTAMPTZ,
|
||||
unpublished_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ─── Documents ────────────────────────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS documents (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
chatbot_id UUID REFERENCES chatbots(id) ON DELETE CASCADE,
|
||||
file_name VARCHAR(500) NOT NULL,
|
||||
file_type VARCHAR(50),
|
||||
file_size BIGINT DEFAULT 0,
|
||||
file_url TEXT,
|
||||
chunk_count INT DEFAULT 0,
|
||||
status VARCHAR(50) DEFAULT 'pending',
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ─── Conversations ────────────────────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS conversations (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
chatbot_id UUID REFERENCES chatbots(id) ON DELETE CASCADE,
|
||||
user_id UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
session_id UUID,
|
||||
language VARCHAR(20) DEFAULT 'en',
|
||||
message_count INT DEFAULT 0,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ─── Messages ─────────────────────────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
conversation_id UUID REFERENCES conversations(id) ON DELETE CASCADE,
|
||||
role VARCHAR(50) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
sources JSONB,
|
||||
model VARCHAR(200),
|
||||
tokens_used INT DEFAULT 0,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ─── Indexes ──────────────────────────────────────────────────────────────────
|
||||
CREATE INDEX IF NOT EXISTS idx_companies_owner ON companies(owner_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_chatbots_company ON chatbots(company_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_chatbots_published ON chatbots(is_published, visibility);
|
||||
CREATE INDEX IF NOT EXISTS idx_documents_chatbot ON documents(chatbot_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_conversations_chatbot ON conversations(chatbot_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_conversations_session ON conversations(session_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_messages_conversation ON messages(conversation_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_subscriptions_user ON subscriptions(user_id);
|
||||
|
||||
-- ─── RLS Policies ─────────────────────────────────────────────────────────────
|
||||
ALTER TABLE companies ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE subscriptions ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE chatbots ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE conversations ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE messages ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Companies: users can only see/edit their own
|
||||
CREATE POLICY "companies_own" ON companies
|
||||
FOR ALL USING (auth.uid() = owner_id);
|
||||
|
||||
-- Subscriptions: users can only see their own
|
||||
CREATE POLICY "subscriptions_own" ON subscriptions
|
||||
FOR ALL USING (auth.uid() = user_id);
|
||||
|
||||
-- Chatbots: owners can manage, public can read published
|
||||
CREATE POLICY "chatbots_owner" ON chatbots
|
||||
FOR ALL USING (
|
||||
company_id IN (SELECT id FROM companies WHERE owner_id = auth.uid())
|
||||
);
|
||||
CREATE POLICY "chatbots_public_read" ON chatbots
|
||||
FOR SELECT USING (is_published = TRUE AND visibility = 'published');
|
||||
|
||||
-- Documents: only chatbot owners
|
||||
CREATE POLICY "documents_owner" ON documents
|
||||
FOR ALL USING (
|
||||
chatbot_id IN (
|
||||
SELECT c.id FROM chatbots c
|
||||
JOIN companies co ON c.company_id = co.id
|
||||
WHERE co.owner_id = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
-- Conversations & Messages: open for anonymous users to create
|
||||
CREATE POLICY "conversations_insert" ON conversations FOR INSERT WITH CHECK (true);
|
||||
CREATE POLICY "conversations_select" ON conversations FOR SELECT USING (true);
|
||||
CREATE POLICY "messages_insert" ON messages FOR INSERT WITH CHECK (true);
|
||||
CREATE POLICY "messages_select" ON messages FOR SELECT USING (true);
|
||||
|
||||
-- ─── Marketplace View ─────────────────────────────────────────────────────────
|
||||
CREATE OR REPLACE VIEW marketplace_chatbots AS
|
||||
SELECT
|
||||
c.id, c.name, c.description, c.category, c.industry,
|
||||
c.languages, c.primary_color, c.welcome_message,
|
||||
c.average_rating, c.total_conversations, c.is_featured,
|
||||
c.published_at, c.created_at,
|
||||
co.name AS company_name, co.logo_url AS company_logo
|
||||
FROM chatbots c
|
||||
JOIN companies co ON c.company_id = co.id
|
||||
JOIN subscriptions s ON co.owner_id = s.user_id
|
||||
WHERE
|
||||
c.visibility = 'published'
|
||||
AND c.is_published = TRUE
|
||||
AND s.status = 'active'
|
||||
AND s.plan IN ('starter', 'pro', 'enterprise');
|
||||
|
||||
-- ─── Auto-unpublish on subscription cancel ────────────────────────────────────
|
||||
CREATE OR REPLACE FUNCTION unpublish_on_subscription_end()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
IF NEW.status IN ('canceled', 'unpaid', 'past_due') THEN
|
||||
UPDATE chatbots
|
||||
SET visibility = 'preview', is_published = FALSE
|
||||
WHERE company_id IN (
|
||||
SELECT id FROM companies WHERE owner_id = NEW.user_id
|
||||
);
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
||||
|
||||
DROP TRIGGER IF EXISTS subscription_status_change ON subscriptions;
|
||||
CREATE TRIGGER subscription_status_change
|
||||
AFTER UPDATE ON subscriptions
|
||||
FOR EACH ROW
|
||||
WHEN (OLD.status IS DISTINCT FROM NEW.status)
|
||||
EXECUTE FUNCTION unpublish_on_subscription_end();
|
||||
Reference in New Issue
Block a user