diff --git a/README.md b/README.md index 4e892b3..9e70f9a 100644 --- a/README.md +++ b/README.md @@ -69,11 +69,10 @@ Create `frontend/.env.local`: ```bash NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY=your-supabase-anon-key -SUPABASE_SECRET_KEY=your-supabase-service-role-key NEXT_PUBLIC_API_BASE_URL=http://localhost:3001 ``` -Supabase values come from the project dashboard. Use the project URL for `SUPABASE_URL` / `NEXT_PUBLIC_SUPABASE_URL`, the service role key for `SUPABASE_SECRET_KEY`, and the anon/public key for `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY`. If your Supabase project shows multiple key formats, use the legacy JWT-style anon and service role keys expected by the Supabase client libraries. +Supabase values come from the project dashboard. Use the project URL for `SUPABASE_URL` / `NEXT_PUBLIC_SUPABASE_URL`, the service role key for the backend `SUPABASE_SECRET_KEY`, and the anon/public key for `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY`. If your Supabase project shows multiple key formats, use the legacy JWT-style anon and service role keys expected by the Supabase client libraries. Provider keys are only needed for the models and email features you plan to use. Model provider keys can be configured in `backend/.env` for the whole instance, or per user in **Account > Models & API Keys**. If a provider key is present in `backend/.env`, that provider is available by default and the matching browser API key field is read-only. diff --git a/backend/src/lib/supabase.ts b/backend/src/lib/supabase.ts index 02bf118..da82186 100644 --- a/backend/src/lib/supabase.ts +++ b/backend/src/lib/supabase.ts @@ -7,6 +7,9 @@ import { createClient } from "@supabase/supabase-js"; export function createServerSupabase() { const url = process.env.SUPABASE_URL || ""; const key = process.env.SUPABASE_SECRET_KEY || ""; + if (!url || !key) { + throw new Error("SUPABASE_URL and SUPABASE_SECRET_KEY must be set"); + } return createClient(url, key, { auth: { persistSession: false } }); } diff --git a/frontend/src/lib/supabase-server.ts b/frontend/src/lib/supabase-server.ts deleted file mode 100644 index 74b159b..0000000 --- a/frontend/src/lib/supabase-server.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { createClient } from "@supabase/supabase-js"; - -/** - * Server-side Supabase client using the service role key. - * Bypasses RLS — only use in API routes after verifying the user. - */ -export function createServerSupabase() { - const url = process.env.NEXT_PUBLIC_SUPABASE_URL || ""; - const key = process.env.SUPABASE_SECRET_KEY || ""; - return createClient(url, key, { auth: { persistSession: false } }); -} - -/** - * Extract and verify the Supabase JWT from the Authorization header. - * Returns the user's UUID string, or throws a Response with 401. - */ -export async function getUserIdFromRequest(req: Request): Promise { - const auth = req.headers.get("authorization") ?? ""; - if (!auth.startsWith("Bearer ")) { - throw new Response("Missing or invalid Authorization header", { status: 401 }); - } - const token = auth.slice(7).trim(); - - const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL || ""; - const serviceKey = process.env.SUPABASE_SECRET_KEY || ""; - - if (!supabaseUrl || !serviceKey) { - // Dev fallback — accept raw token as user ID - return token; - } - - const admin = createClient(supabaseUrl, serviceKey, { auth: { persistSession: false } }); - const { data } = await admin.auth.getUser(token); - if (!data.user) { - throw new Response("Invalid or expired token", { status: 401 }); - } - return data.user.id; -}