diff --git a/package.json b/package.json index 69e18a11..d79edcf1 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,11 @@ "build": "yarn workspaces run build", "test": "yarn workspaces run test", "dev": "cross-env SOURCEBOT_TENANT_MODE=single npm-run-all --print-label dev:start", - "dev:mt": "cross-env SOURCEBOT_TENANT_MODE=multi npm-run-all --print-label dev:start", + "dev:mt": "cross-env SOURCEBOT_TENANT_MODE=multi npm-run-all --print-label dev:start:mt", "dev:start": "yarn workspace @sourcebot/db prisma:migrate:dev && cross-env npm-run-all --print-label --parallel dev:zoekt dev:backend dev:web", + "dev:start:mt": "yarn workspace @sourcebot/db prisma:migrate:dev && cross-env npm-run-all --print-label --parallel dev:zoekt:mt dev:backend dev:web", "dev:zoekt": "export PATH=\"$PWD/bin:$PATH\" && export SRC_TENANT_ENFORCEMENT_MODE=none && zoekt-webserver -index .sourcebot/index -rpc", + "dev:zoekt:mt": "export PATH=\"$PWD/bin:$PATH\" && export SRC_TENANT_ENFORCEMENT_MODE=strict && zoekt-webserver -index .sourcebot/index -rpc", "dev:backend": "yarn workspace @sourcebot/backend dev:watch", "dev:web": "yarn workspace @sourcebot/web dev" }, diff --git a/packages/web/src/actions.ts b/packages/web/src/actions.ts index ab4c3f9f..64798d54 100644 --- a/packages/web/src/actions.ts +++ b/packages/web/src/actions.ts @@ -1,12 +1,12 @@ 'use server'; import Ajv from "ajv"; -import { getUser } from "./data/user"; -import { auth } from "./auth"; -import { notAuthenticated, notFound, ServiceError, unexpectedError } from "./lib/serviceError"; +import { auth, getCurrentUserOrg } from "./auth"; +import { notAuthenticated, notFound, ServiceError, unexpectedError } from "@/lib/serviceError"; import { prisma } from "@/prisma"; import { StatusCodes } from "http-status-codes"; -import { ErrorCode } from "./lib/errorCodes"; +import { ErrorCode } from "@/lib/errorCodes"; +import { isServiceError } from "@/lib/utils"; import { githubSchema } from "@sourcebot/schemas/v3/github.schema"; import { encrypt } from "@sourcebot/crypto" @@ -15,31 +15,9 @@ const ajv = new Ajv({ }); export const createSecret = async (key: string, value: string): Promise<{ success: boolean } | ServiceError> => { - const session = await auth(); - if (!session) { - return notAuthenticated(); - } - - const user = await getUser(session.user.id); - if (!user) { - return unexpectedError("User not found"); - } - const orgId = user.activeOrgId; - if (!orgId) { - return unexpectedError("User has no active org"); - } - - // @todo: refactor this into a shared function - const membership = await prisma.userToOrg.findUnique({ - where: { - orgId_userId: { - userId: session.user.id, - orgId, - } - }, - }); - if (!membership) { - return notFound(); + const orgId = await getCurrentUserOrg(); + if (isServiceError(orgId)) { + return orgId; } try { @@ -62,30 +40,9 @@ export const createSecret = async (key: string, value: string): Promise<{ succes } export const getSecrets = async (): Promise<{ createdAt: Date; key: string; }[] | ServiceError> => { - const session = await auth(); - if (!session) { - return notAuthenticated(); - } - - const user = await getUser(session.user.id); - if (!user) { - return unexpectedError("User not found"); - } - const orgId = user.activeOrgId; - if (!orgId) { - return unexpectedError("User has no active org"); - } - - const membership = await prisma.userToOrg.findUnique({ - where: { - orgId_userId: { - userId: session.user.id, - orgId, - } - }, - }); - if (!membership) { - return notFound(); + const orgId = await getCurrentUserOrg(); + if (isServiceError(orgId)) { + return orgId; } const secrets = await prisma.secret.findMany({ @@ -105,30 +62,9 @@ export const getSecrets = async (): Promise<{ createdAt: Date; key: string; }[] } export const deleteSecret = async (key: string): Promise<{ success: boolean } | ServiceError> => { - const session = await auth(); - if (!session) { - return notAuthenticated(); - } - - const user = await getUser(session.user.id); - if (!user) { - return unexpectedError("User not found"); - } - const orgId = user.activeOrgId; - if (!orgId) { - return unexpectedError("User has no active org"); - } - - const membership = await prisma.userToOrg.findUnique({ - where: { - orgId_userId: { - userId: session.user.id, - orgId, - } - }, - }); - if (!membership) { - return notFound(); + const orgId = await getCurrentUserOrg(); + if (isServiceError(orgId)) { + return orgId; } await prisma.secret.delete({ @@ -206,31 +142,9 @@ export const switchActiveOrg = async (orgId: number): Promise<{ id: number } | S } export const createConnection = async (config: string): Promise<{ id: number } | ServiceError> => { - const session = await auth(); - if (!session) { - return notAuthenticated(); - } - - const user = await getUser(session.user.id); - if (!user) { - return unexpectedError("User not found"); - } - const orgId = user.activeOrgId; - if (!orgId) { - return unexpectedError("User has no active org"); - } - - // @todo: refactor this into a shared function - const membership = await prisma.userToOrg.findUnique({ - where: { - orgId_userId: { - userId: session.user.id, - orgId, - } - }, - }); - if (!membership) { - return notFound(); + const orgId = await getCurrentUserOrg(); + if (isServiceError(orgId)) { + return orgId; } let parsedConfig; diff --git a/packages/web/src/app/api/(server)/repos/route.ts b/packages/web/src/app/api/(server)/repos/route.ts index def073c1..eac6d2e3 100644 --- a/packages/web/src/app/api/(server)/repos/route.ts +++ b/packages/web/src/app/api/(server)/repos/route.ts @@ -1,8 +1,15 @@ 'use server'; import { listRepositories } from "@/lib/server/searchService"; +import { getCurrentUserOrg } from "../../../../auth"; +import { isServiceError } from "@/lib/utils"; export const GET = async () => { - const response = await listRepositories(); + const orgId = await getCurrentUserOrg(); + if (isServiceError(orgId)) { + return orgId; + } + + const response = await listRepositories(orgId); return Response.json(response); } \ No newline at end of file diff --git a/packages/web/src/app/api/(server)/search/route.ts b/packages/web/src/app/api/(server)/search/route.ts index 4255d33c..7301fc9c 100644 --- a/packages/web/src/app/api/(server)/search/route.ts +++ b/packages/web/src/app/api/(server)/search/route.ts @@ -5,19 +5,17 @@ import { searchRequestSchema } from "@/lib/schemas"; import { schemaValidationError, serviceErrorResponse } from "@/lib/serviceError"; import { isServiceError } from "@/lib/utils"; import { NextRequest } from "next/server"; +import { getCurrentUserOrg } from "../../../../auth"; export const POST = async (request: NextRequest) => { + const orgId = await getCurrentUserOrg(); + if (isServiceError(orgId)) { + return orgId; + } + + console.log(`Searching for org ${orgId}`); const body = await request.json(); - const tenantId = request.headers.get("X-Tenant-ID"); - - console.log(`Search request received. Tenant ID: ${tenantId}`); - - const parsed = await searchRequestSchema.safeParseAsync({ - ...body, - ...(tenantId ? { - tenantId: parseInt(tenantId) - } : {}), - }); + const parsed = await searchRequestSchema.safeParseAsync(body); if (!parsed.success) { return serviceErrorResponse( schemaValidationError(parsed.error) @@ -25,7 +23,7 @@ export const POST = async (request: NextRequest) => { } - const response = await search(parsed.data); + const response = await search(parsed.data, orgId); if (isServiceError(response)) { return serviceErrorResponse(response); } diff --git a/packages/web/src/app/api/(server)/source/route.ts b/packages/web/src/app/api/(server)/source/route.ts index 2c245374..d171a6c4 100644 --- a/packages/web/src/app/api/(server)/source/route.ts +++ b/packages/web/src/app/api/(server)/source/route.ts @@ -5,8 +5,14 @@ import { getFileSource } from "@/lib/server/searchService"; import { schemaValidationError, serviceErrorResponse } from "@/lib/serviceError"; import { isServiceError } from "@/lib/utils"; import { NextRequest } from "next/server"; +import { getCurrentUserOrg } from "@/auth"; export const POST = async (request: NextRequest) => { + const orgId = await getCurrentUserOrg(); + if (isServiceError(orgId)) { + return orgId; + } + const body = await request.json(); const parsed = await fileSourceRequestSchema.safeParseAsync(body); if (!parsed.success) { @@ -15,7 +21,7 @@ export const POST = async (request: NextRequest) => { ); } - const response = await getFileSource(parsed.data); + const response = await getFileSource(parsed.data, orgId); if (isServiceError(response)) { return serviceErrorResponse(response); } diff --git a/packages/web/src/app/browse/[...path]/page.tsx b/packages/web/src/app/browse/[...path]/page.tsx index 47108622..010efd01 100644 --- a/packages/web/src/app/browse/[...path]/page.tsx +++ b/packages/web/src/app/browse/[...path]/page.tsx @@ -7,6 +7,7 @@ import { CodePreview } from "./codePreview"; import { PageNotFound } from "@/app/components/pageNotFound"; import { ErrorCode } from "@/lib/errorCodes"; import { LuFileX2, LuBookX } from "react-icons/lu"; +import { getCurrentUserOrg } from "@/auth"; interface BrowsePageProps { params: { @@ -44,9 +45,18 @@ export default async function BrowsePage({ } })(); + const orgId = await getCurrentUserOrg(); + if (isServiceError(orgId)) { + return ( + <> + Error: {orgId.message} + > + ) + } + // @todo (bkellam) : We should probably have a endpoint to fetch repository metadata // given it's name or id. - const reposResponse = await listRepositories(); + const reposResponse = await listRepositories(orgId); if (isServiceError(reposResponse)) { // @todo : proper error handling return ( @@ -98,6 +108,7 @@ export default async function BrowsePage({ path={path} repoName={repoName} revisionName={revisionName ?? 'HEAD'} + orgId={orgId} /> )} @@ -108,19 +119,21 @@ interface CodePreviewWrapper { path: string, repoName: string, revisionName: string, + orgId: number, } const CodePreviewWrapper = async ({ path, repoName, revisionName, + orgId, }: CodePreviewWrapper) => { // @todo: this will depend on `pathType`. const fileSourceResponse = await getFileSource({ fileName: path, repository: repoName, branch: revisionName, - }); + }, orgId); if (isServiceError(fileSourceResponse)) { if (fileSourceResponse.errorCode === ErrorCode.FILE_NOT_FOUND) { diff --git a/packages/web/src/app/page.tsx b/packages/web/src/app/page.tsx index 81c19628..335a4754 100644 --- a/packages/web/src/app/page.tsx +++ b/packages/web/src/app/page.tsx @@ -11,93 +11,102 @@ import { Separator } from "@/components/ui/separator"; import { SymbolIcon } from "@radix-ui/react-icons"; import { UpgradeToast } from "./components/upgradeToast"; import Link from "next/link"; +import { getCurrentUserOrg } from "../auth" export default async function Home() { + const orgId = await getCurrentUserOrg(); + return (