feat: auth, persistence, and AI integration
- Cookie-based auth via backend proxy (httpOnly JWTs) - Supabase Postgres persistence for sessions/messages/profiles + RLS - Fix cross-user session leak (token cache keyed by full token, not 50-char prefix) - Fix missing table grants (42501) via migration; auto-provision profiles on user creation - Chat validation, ownership checks, rate limiting, /api/chat/sessions route ordering - Frontend auth-state reset + credentials include - OpenRouter AI provider (OpenAI-compatible base URL, reasoning disabled) - Tests: chatValidation, appState
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
-- Create sessions table
|
||||
CREATE TABLE public.sessions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
grade TEXT,
|
||||
subject TEXT,
|
||||
chapter TEXT,
|
||||
preview TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
-- Create messages table
|
||||
CREATE TABLE public.messages (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
session_id UUID NOT NULL REFERENCES public.sessions(id) ON DELETE CASCADE,
|
||||
role TEXT NOT NULL CHECK (role IN ('user', 'assistant')),
|
||||
text TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
-- Create profiles table (optional, for future user metadata)
|
||||
CREATE TABLE public.profiles (
|
||||
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
email TEXT NOT NULL,
|
||||
display_name TEXT,
|
||||
avatar_url TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
-- Create indexes for faster queries
|
||||
CREATE INDEX idx_sessions_user_id ON public.sessions(user_id);
|
||||
CREATE INDEX idx_messages_session_id ON public.messages(session_id);
|
||||
|
||||
-- Enable RLS
|
||||
ALTER TABLE public.sessions ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.messages ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- RLS Policies for sessions: users can CRUD only their own sessions
|
||||
CREATE POLICY "Users can view own sessions"
|
||||
ON public.sessions FOR SELECT
|
||||
USING (auth.uid() = user_id);
|
||||
|
||||
CREATE POLICY "Users can create sessions"
|
||||
ON public.sessions FOR INSERT
|
||||
WITH CHECK (auth.uid() = user_id);
|
||||
|
||||
CREATE POLICY "Users can update own sessions"
|
||||
ON public.sessions FOR UPDATE
|
||||
USING (auth.uid() = user_id)
|
||||
WITH CHECK (auth.uid() = user_id);
|
||||
|
||||
CREATE POLICY "Users can delete own sessions"
|
||||
ON public.sessions FOR DELETE
|
||||
USING (auth.uid() = user_id);
|
||||
|
||||
-- RLS Policies for messages: users can CRUD only messages in their own sessions
|
||||
CREATE POLICY "Users can view messages in own sessions"
|
||||
ON public.messages FOR SELECT
|
||||
USING (session_id IN (SELECT id FROM public.sessions WHERE user_id = auth.uid()));
|
||||
|
||||
CREATE POLICY "Users can insert messages in own sessions"
|
||||
ON public.messages FOR INSERT
|
||||
WITH CHECK (session_id IN (SELECT id FROM public.sessions WHERE user_id = auth.uid()));
|
||||
|
||||
CREATE POLICY "Users can delete own messages"
|
||||
ON public.messages FOR DELETE
|
||||
USING (session_id IN (SELECT id FROM public.sessions WHERE user_id = auth.uid()));
|
||||
|
||||
-- RLS Policies for profiles
|
||||
CREATE POLICY "Users can view own profile"
|
||||
ON public.profiles FOR SELECT
|
||||
USING (auth.uid() = id);
|
||||
|
||||
CREATE POLICY "Users can update own profile"
|
||||
ON public.profiles FOR UPDATE
|
||||
USING (auth.uid() = id)
|
||||
WITH CHECK (auth.uid() = id);
|
||||
Reference in New Issue
Block a user