Files
Portfolio/supabase/migrations/001_create_chat_tables.sql
T
damjan_savicandClaude Opus 4.5 e1bbe5455d Initial commit: Portfolio Website
Vollständige Next.js 15 Portfolio-Website mit:
- Blog-System mit 100+ Artikeln
- Supabase-Integration
- Responsive Design mit Tailwind CSS
- TypeScript-Konfiguration
- Testing-Setup mit Vitest und Playwright

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 15:07:20 +01:00

156 lines
6.1 KiB
PL/PgSQL

-- Chat Tables Migration
-- Creates tables for chatbot functionality with visitor sessions and message history
-- Version: 001
-- Date: 2026-01-25
-- ============================================================================
-- Table: chat_sessions
-- Stores chatbot session information for visitors
-- ============================================================================
CREATE TABLE IF NOT EXISTS chat_sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
visitor_id TEXT NOT NULL,
metadata JSONB DEFAULT '{}'::jsonb,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
);
-- Index for quick lookup by visitor_id (used for session continuity)
CREATE INDEX IF NOT EXISTS idx_chat_sessions_visitor_id ON chat_sessions(visitor_id);
-- Index for ordering sessions by creation time
CREATE INDEX IF NOT EXISTS idx_chat_sessions_created_at ON chat_sessions(created_at DESC);
-- Comment on table
COMMENT ON TABLE chat_sessions IS 'Stores chatbot sessions for website visitors';
COMMENT ON COLUMN chat_sessions.visitor_id IS 'Unique identifier for the visitor (generated client-side or from fingerprint)';
COMMENT ON COLUMN chat_sessions.metadata IS 'Additional session data (locale, user_agent, referrer, etc.)';
-- ============================================================================
-- Table: chat_messages
-- Stores individual chat messages within a session
-- ============================================================================
CREATE TABLE IF NOT EXISTS chat_messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
session_id UUID NOT NULL REFERENCES chat_sessions(id) ON DELETE CASCADE,
role TEXT NOT NULL CHECK (role IN ('user', 'assistant', 'system')),
content TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
);
-- Index for fetching messages by session (primary query pattern)
CREATE INDEX IF NOT EXISTS idx_chat_messages_session_id ON chat_messages(session_id);
-- Composite index for fetching messages in order within a session
CREATE INDEX IF NOT EXISTS idx_chat_messages_session_created ON chat_messages(session_id, created_at ASC);
-- Comment on table
COMMENT ON TABLE chat_messages IS 'Stores individual messages in chatbot conversations';
COMMENT ON COLUMN chat_messages.role IS 'Message sender role: user, assistant (AI), or system (instructions)';
COMMENT ON COLUMN chat_messages.content IS 'The message text content';
-- ============================================================================
-- Updated At Trigger for chat_sessions
-- Automatically updates the updated_at column when a session is modified
-- ============================================================================
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER update_chat_sessions_updated_at
BEFORE UPDATE ON chat_sessions
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
-- ============================================================================
-- Row Level Security (RLS)
-- Enabled for production security - server uses service role key to bypass
-- ============================================================================
-- Enable RLS on chat_sessions
ALTER TABLE chat_sessions ENABLE ROW LEVEL SECURITY;
-- Enable RLS on chat_messages
ALTER TABLE chat_messages ENABLE ROW LEVEL SECURITY;
-- ============================================================================
-- RLS Policies for chat_sessions
-- ============================================================================
-- Policy: Allow service role full access (for server-side API routes)
-- Note: Service role key automatically bypasses RLS, but this is explicit
CREATE POLICY "Service role has full access to chat_sessions"
ON chat_sessions
FOR ALL
TO service_role
USING (true)
WITH CHECK (true);
-- Policy: Allow visitors to read their own sessions (for potential future client-side access)
CREATE POLICY "Visitors can read their own sessions"
ON chat_sessions
FOR SELECT
TO anon, authenticated
USING (visitor_id = current_setting('request.headers')::json->>'x-visitor-id');
-- Policy: Allow visitors to create sessions (for potential future client-side access)
CREATE POLICY "Visitors can create sessions"
ON chat_sessions
FOR INSERT
TO anon, authenticated
WITH CHECK (visitor_id = current_setting('request.headers')::json->>'x-visitor-id');
-- ============================================================================
-- RLS Policies for chat_messages
-- ============================================================================
-- Policy: Allow service role full access (for server-side API routes)
CREATE POLICY "Service role has full access to chat_messages"
ON chat_messages
FOR ALL
TO service_role
USING (true)
WITH CHECK (true);
-- Policy: Allow visitors to read messages from their sessions
CREATE POLICY "Visitors can read messages from their sessions"
ON chat_messages
FOR SELECT
TO anon, authenticated
USING (
EXISTS (
SELECT 1 FROM chat_sessions
WHERE chat_sessions.id = chat_messages.session_id
AND chat_sessions.visitor_id = current_setting('request.headers')::json->>'x-visitor-id'
)
);
-- Policy: Allow visitors to insert messages into their sessions
CREATE POLICY "Visitors can insert messages into their sessions"
ON chat_messages
FOR INSERT
TO anon, authenticated
WITH CHECK (
EXISTS (
SELECT 1 FROM chat_sessions
WHERE chat_sessions.id = chat_messages.session_id
AND chat_sessions.visitor_id = current_setting('request.headers')::json->>'x-visitor-id'
)
);
-- ============================================================================
-- Grants
-- ============================================================================
-- Grant usage on tables to authenticated and anon roles
GRANT SELECT, INSERT ON chat_sessions TO anon, authenticated;
GRANT SELECT, INSERT ON chat_messages TO anon, authenticated;
-- Grant all to service role (for server-side operations)
GRANT ALL ON chat_sessions TO service_role;
GRANT ALL ON chat_messages TO service_role;