| import { getSupabaseAdmin } from "@/lib/supabase/admin"; |
| import { createServerClient } from "@supabase/ssr"; |
| import { cookies } from "next/headers"; |
| import crypto from "node:crypto"; |
|
|
| export type RequestIdentity = { |
| organizationId: string; |
| userId: string; |
| }; |
|
|
| export async function resolveRequestIdentity(): Promise<RequestIdentity> { |
| const cookieStore = await cookies(); |
| |
| const supabase = createServerClient( |
| process.env.NEXT_PUBLIC_SUPABASE_URL!, |
| process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, |
| { |
| cookies: { |
| getAll() { |
| return cookieStore.getAll(); |
| }, |
| setAll() {}, |
| }, |
| } |
| ); |
|
|
| const { data: { user }, error } = await supabase.auth.getUser(); |
| |
| if (error || !user) { |
| throw new Error("Missing auth session"); |
| } |
| |
| const userId = user.id; |
|
|
| const adminClient = getSupabaseAdmin(); |
| const { data: member, error: memberError } = await adminClient |
| .from("members") |
| .select("organization_id") |
| .eq("user_id", userId) |
| .order("created_at", { ascending: true }) |
| .limit(1) |
| .maybeSingle(); |
|
|
| if (memberError && memberError.code !== "PGRST116") { |
| throw new Error(`Failed to resolve organization: ${memberError.message}`); |
| } |
|
|
| |
| let organizationId = member?.organization_id; |
| if (!organizationId) { |
| const newOrgId = crypto.randomUUID(); |
| const { error: orgError } = await adminClient.from("organizations").insert({ |
| id: newOrgId, |
| name: `Personal Org (${user.email})`, |
| slug: `org-${newOrgId.slice(0, 8)}`, |
| }); |
| |
| if (orgError) throw new Error("Failed to bootstrap new organization for user"); |
|
|
| const { error: memberInsertError } = await adminClient.from("members").insert({ |
| organization_id: newOrgId, |
| user_id: userId, |
| role: "owner" |
| }); |
|
|
| if (memberInsertError) throw new Error("Failed to create membership for new organization"); |
| organizationId = newOrgId; |
| } |
|
|
| return { organizationId, userId }; |
| } |
|
|