From bb5a3b541ce284d1af9f819b4060c4ef8242d3db Mon Sep 17 00:00:00 2001 From: Rob Simmons Date: Thu, 29 Oct 2026 13:22:54 -0400 Subject: [PATCH 1/2] refactor: getProjectForViewer --- .../[projectName]/download/route.ts | 15 +++++---------- src/app/[userName]/[projectName]/page.tsx | 19 +++++-------------- .../preview/[...relPath]/route.ts | 14 ++++---------- src/lib/server/util.ts | 19 ++++++++++++++++++- 4 files changed, 32 insertions(+), 35 deletions(-) diff --git a/src/app/[userName]/[projectName]/download/route.ts b/src/app/[userName]/[projectName]/download/route.ts index 8b4e8f4e..ab529f3d 100644 --- a/src/app/[userName]/[projectName]/download/route.ts +++ b/src/app/[userName]/[projectName]/download/route.ts @@ -6,8 +6,7 @@ import { notFound } from 'next/navigation' import z from 'zod' import { requireAuth } from '@/lib/server/auth' -import { getDb } from '@/lib/server/db' -import { canAccessProject } from '@/lib/server/util' +import { getProjectForViewer } from '@/lib/server/util' const zParams = z.object({ userName: zUserName, @@ -35,14 +34,10 @@ export async function GET(_req: Request, { params }: { params: Promise const { userName, projectName } = parsed.data const session = await requireAuth() - const db = getDb() - const owner = await db.user.findUnique({ where: { name: userName } }) - if (!owner) notFound() - const project = await db.project.findUnique({ - where: { userId_name: { userId: owner.id, name: projectName } }, - }) - // 404 rather than 403 to avoid leaking the existence of inaccessible projects. - if (!project || !canAccessProject(session.user, project)) notFound() + + const proj = await getProjectForViewer(session.user, userName, projectName) + if (!proj) notFound() // 404 rather than 403 to avoid leaking the existence of inaccessible projects. + const { owner, project } = proj return new Response(iteratorToStream(generateProjectTgz(owner, project.id)), { headers: { diff --git a/src/app/[userName]/[projectName]/page.tsx b/src/app/[userName]/[projectName]/page.tsx index 5b17af6d..418dfaa0 100644 --- a/src/app/[userName]/[projectName]/page.tsx +++ b/src/app/[userName]/[projectName]/page.tsx @@ -4,9 +4,8 @@ import { connection } from 'next/server' import z from 'zod' import { requireAuth } from '@/lib/server/auth' -import { getDb } from '@/lib/server/db' import { getShardCoordinator } from '@/lib/server/shardConnection' -import { canAccessProject } from '@/lib/server/util' +import { getProjectForViewer } from '@/lib/server/util' const zParams = z.object({ userName: zUserName, @@ -26,22 +25,14 @@ export default async function EditorSession({ params: params_ }: { params: Promi const params = parsed.data const session = await requireAuth() - const viewer = session.user - const db = getDb() - const owner = await db.user.findUnique({ - where: { name: params.userName }, - }) - if (!owner) notFound() - - const project = await db.project.findUnique({ - where: { userId_name: { userId: owner.id, name: params.projectName } }, - }) - if (!project || !canAccessProject(viewer, project)) notFound() + const proj = await getProjectForViewer(session.user, params.userName, params.projectName) + if (!proj) notFound() // 404 rather than 403 to avoid leaking the existence of inaccessible projects. + const { owner, project } = proj const coordinator = getShardCoordinator() // may throw to error boundary (e.g. if the project folder isn't accessible) - const iframeUrl = await coordinator.ensureSession(viewer, owner, project) + const iframeUrl = await coordinator.ensureSession(session.user, owner, project) // TODO: VSC should be sandboxed but can't be opaque-origin: need a subdomain. return