diff --git a/apps/web/src/api/server-functions/getSupabaseSession.ts b/apps/web/src/api/server-functions/getSupabaseSession.ts index 0e833ee14..934cb212f 100644 --- a/apps/web/src/api/server-functions/getSupabaseSession.ts +++ b/apps/web/src/api/server-functions/getSupabaseSession.ts @@ -2,6 +2,7 @@ import type { AuthError, Session, SupabaseClient } from '@supabase/supabase-js'; import { createServerFn } from '@tanstack/react-start'; import type { SimplifiedSupabaseSession } from '@/integrations/supabase/getSupabaseUserClient'; import { getSupabaseServerClient } from '@/integrations/supabase/server'; +import { isServer } from '@/lib/window'; import { isTokenExpired } from '../auth_helpers/expiration-helpers'; export const extractSimplifiedSupabaseSession = async ( diff --git a/apps/web/src/routes/screenshots/_content/metrics.$metricId.content.tsx b/apps/web/src/routes/screenshots/_content/metrics.$metricId.content.tsx index d27fb932d..151bd3aff 100644 --- a/apps/web/src/routes/screenshots/_content/metrics.$metricId.content.tsx +++ b/apps/web/src/routes/screenshots/_content/metrics.$metricId.content.tsx @@ -1,4 +1,5 @@ import { createFileRoute } from '@tanstack/react-router'; +import { getCookie } from '@tanstack/react-start/server'; import { z } from 'zod'; import { useGetUserBasicInfo } from '@/api/buster_rest/users/useGetUserInfo'; import { Route as ScreenshotsRoute } from '../_content'; @@ -8,6 +9,15 @@ export const Route = createFileRoute('/screenshots/_content/metrics/$metricId/co component: RouteComponent, validateSearch: GetMetricScreenshotQuerySchema, ssr: true, + beforeLoad: async ({ context }) => { + const supabaseCookie = await getCookie('sb-127-auth-token'); + console.log('--------------------------------'); + console.log(supabaseCookie); + console.log('--------------------------------'); + return { + supabaseCookie, + }; + }, }); function RouteComponent() { diff --git a/apps/web/src/routes/screenshots/metrics.$metricId.index.tsx b/apps/web/src/routes/screenshots/metrics.$metricId.index.tsx index ce9b35c2d..00416cd68 100644 --- a/apps/web/src/routes/screenshots/metrics.$metricId.index.tsx +++ b/apps/web/src/routes/screenshots/metrics.$metricId.index.tsx @@ -2,6 +2,7 @@ import { createServerFileRoute } from '@tanstack/react-start/server'; import { chromium } from 'playwright'; import { z } from 'zod'; import { getMetric } from '@/api/buster_rest/metrics'; +import { env } from '@/env'; import { getSupabaseServerClient } from '@/integrations/supabase/server'; import { Route as MetricContentRoute } from './_content/metrics.$metricId.content'; @@ -23,6 +24,7 @@ export const ServerRoute = createServerFileRoute('/screenshots/metrics/$metricId const bearerToken = request.headers.get('Authorization') || ''; const accessToken = bearerToken.replace('Bearer ', ''); const supabase = getSupabaseServerClient(); + const { data: { user }, } = await supabase.auth.getUser(accessToken); @@ -31,24 +33,56 @@ export const ServerRoute = createServerFileRoute('/screenshots/metrics/$metricId return new Response('Unauthorized', { status: 401 }); } - console.time('capture screenshot'); const { metricId } = GetMetricScreenshotParamsSchema.parse(params); const { version_number, type, width, height } = GetMetricScreenshotQuerySchema.parse( Object.fromEntries(new URL(request.url).searchParams) ); const origin = new URL(request.url).origin; - console.timeLog('capture screenshot', 'params parsed'); + // For Playwright, we need to reconstruct the session from the JWT + // Decode the JWT to get expiry time + const jwtPayload = JSON.parse(Buffer.from(accessToken.split('.')[1], 'base64').toString()); + + const session = { + access_token: accessToken, + token_type: 'bearer', + expires_in: 3600, + expires_at: jwtPayload.exp, + refresh_token: '', + user: user, + }; + + console.time('capture screenshot'); + const browser = await chromium.launch(); console.timeLog('capture screenshot', 'browser launched'); try { - // Create a session object for Supabase - // Create browser context with authentication cookies const context = await browser.newContext({ viewport: { width, height }, }); + // Extract project ref from Supabase URL (e.g., "abcdefg" from "abcdefg.supabase.co") + const projectRef = '127'; + + // Format cookie value as Supabase expects: base64- + const cookieValue = `base64-${Buffer.from(JSON.stringify(session)).toString('base64')}`; + + console.log('Project ref:', projectRef); + console.log('Cookie name:', `sb-${projectRef}-auth-token`); + + await context.addCookies([ + { + name: `sb-${projectRef}-auth-token`, + value: cookieValue, + domain: new URL(env.VITE_PUBLIC_URL).hostname, + path: '/', + httpOnly: true, + secure: true, + sameSite: 'Lax', + }, + ]); + const page = await context.newPage(); console.timeLog('capture screenshot', 'page created with auth cookie');