From 9bbd3b681675973656cc9c8bde060d0a6870388f Mon Sep 17 00:00:00 2001 From: Zai Shi Date: Tue, 20 May 2025 17:29:44 -0700 Subject: [PATCH] update --- .../20250520185503_rename_neon/migration.sql | 1 + apps/backend/prisma/schema.prisma | 2 +- .../integrations/custom/internal/confirm/route.tsx | 4 ++-- .../integrations/custom/projects/provision/route.tsx | 2 +- .../custom/projects/transfer/confirm/check/route.tsx | 4 ++-- .../custom/projects/transfer/confirm/route.tsx | 4 ++-- .../transfer/confirm/verification-code-handler.tsx | 8 ++++---- .../integrations/custom/projects/transfer/route.tsx | 8 ++++---- apps/backend/src/app/api/latest/integrations/idp.ts | 12 ++++++------ .../integrations/neon/internal/confirm/route.tsx | 4 ++-- .../integrations/neon/projects/provision/route.tsx | 2 +- .../transfer/confirm/verification-code-handler.tsx | 4 ++-- .../integrations/neon/projects/transfer/route.tsx | 4 ++-- .../api/v1/integrations/custom/oauth.test.ts | 8 ++++---- .../endpoints/api/v1/integrations/neon/oauth.test.ts | 4 ++-- 15 files changed, 36 insertions(+), 35 deletions(-) diff --git a/apps/backend/prisma/migrations/20250520185503_rename_neon/migration.sql b/apps/backend/prisma/migrations/20250520185503_rename_neon/migration.sql index 0301f6246..85f07f091 100644 --- a/apps/backend/prisma/migrations/20250520185503_rename_neon/migration.sql +++ b/apps/backend/prisma/migrations/20250520185503_rename_neon/migration.sql @@ -5,3 +5,4 @@ ALTER TYPE "VerificationCodeType" RENAME VALUE 'NEON_INTEGRATION_PROJECT_TRANSFE ALTER TABLE "NeonProvisionedProject" RENAME TO "ProvisionedProject"; ALTER TABLE "ProvisionedProject" RENAME CONSTRAINT "NeonProvisionedProject_pkey" TO "ProvisionedProject_pkey"; ALTER TABLE "ProvisionedProject" RENAME CONSTRAINT "NeonProvisionedProject_projectId_fkey" TO "ProvisionedProject_projectId_fkey"; +ALTER TABLE "ProvisionedProject" RENAME COLUMN "neonClientId" TO "externalProjectId"; diff --git a/apps/backend/prisma/schema.prisma b/apps/backend/prisma/schema.prisma index 43d1de59d..f06726958 100644 --- a/apps/backend/prisma/schema.prisma +++ b/apps/backend/prisma/schema.prisma @@ -641,7 +641,7 @@ model ProvisionedProject { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt - neonClientId String? + externalProjectId String } //#region Events diff --git a/apps/backend/src/app/api/latest/integrations/custom/internal/confirm/route.tsx b/apps/backend/src/app/api/latest/integrations/custom/internal/confirm/route.tsx index 2459494b2..ef364c5ad 100644 --- a/apps/backend/src/app/api/latest/integrations/custom/internal/confirm/route.tsx +++ b/apps/backend/src/app/api/latest/integrations/custom/internal/confirm/route.tsx @@ -18,7 +18,7 @@ export const POST = createSmartRouteHandler({ body: yupObject({ interaction_uid: yupString().defined(), project_id: yupString().defined(), - neon_project_name: yupString().optional(), + external_project_name: yupString().optional(), }).defined(), }), response: yupObject({ @@ -33,7 +33,7 @@ export const POST = createSmartRouteHandler({ const set = await prismaClient.apiKeySet.create({ data: { projectId: req.body.project_id, - description: `Auto-generated for Neon${req.body.neon_project_name ? ` (${req.body.neon_project_name})` : ""}`, + description: `Auto-generated for ${req.body.external_project_name ? `"${req.body.external_project_name}"` : "an external project"}`, expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365 * 100), superSecretAdminKey: `sak_${generateSecureRandomString()}`, }, diff --git a/apps/backend/src/app/api/latest/integrations/custom/projects/provision/route.tsx b/apps/backend/src/app/api/latest/integrations/custom/projects/provision/route.tsx index 79f7a22ff..c454ac285 100644 --- a/apps/backend/src/app/api/latest/integrations/custom/projects/provision/route.tsx +++ b/apps/backend/src/app/api/latest/integrations/custom/projects/provision/route.tsx @@ -54,7 +54,7 @@ export const POST = createSmartRouteHandler({ await prismaClient.provisionedProject.create({ data: { projectId: createdProject.id, - neonClientId: clientId, + externalProjectId: clientId, }, }); diff --git a/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/confirm/check/route.tsx b/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/confirm/check/route.tsx index d5d21bc8e..ddb11baf5 100644 --- a/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/confirm/check/route.tsx +++ b/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/confirm/check/route.tsx @@ -1,3 +1,3 @@ -import { neonIntegrationProjectTransferCodeHandler } from "../verification-code-handler"; +import { integrationProjectTransferCodeHandler } from "../verification-code-handler"; -export const POST = neonIntegrationProjectTransferCodeHandler.checkHandler; +export const POST = integrationProjectTransferCodeHandler.checkHandler; diff --git a/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/confirm/route.tsx b/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/confirm/route.tsx index 09c5c0ca4..3ca108fa2 100644 --- a/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/confirm/route.tsx +++ b/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/confirm/route.tsx @@ -1,3 +1,3 @@ -import { neonIntegrationProjectTransferCodeHandler } from "./verification-code-handler"; +import { integrationProjectTransferCodeHandler } from "./verification-code-handler"; -export const POST = neonIntegrationProjectTransferCodeHandler.postHandler; +export const POST = integrationProjectTransferCodeHandler.postHandler; diff --git a/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/confirm/verification-code-handler.tsx b/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/confirm/verification-code-handler.tsx index 32a1ad2d2..88a1426ad 100644 --- a/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/confirm/verification-code-handler.tsx +++ b/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/confirm/verification-code-handler.tsx @@ -5,7 +5,7 @@ import { KnownErrors } from "@stackframe/stack-shared"; import { yupNumber, yupObject, yupString } from "@stackframe/stack-shared/dist/schema-fields"; import { StatusError, throwErr } from "@stackframe/stack-shared/dist/utils/errors"; -export const neonIntegrationProjectTransferCodeHandler = createVerificationCodeHandler({ +export const integrationProjectTransferCodeHandler = createVerificationCodeHandler({ metadata: { post: { hidden: true, @@ -16,7 +16,7 @@ export const neonIntegrationProjectTransferCodeHandler = createVerificationCodeH }, type: VerificationCodeType.INTEGRATION_PROJECT_TRANSFER, data: yupObject({ - neon_client_id: yupString().defined(), + external_project_id: yupString().defined(), project_id: yupString().defined(), }).defined(), method: yupObject({}), @@ -34,7 +34,7 @@ export const neonIntegrationProjectTransferCodeHandler = createVerificationCodeH const provisionedProjects = await prismaClient.provisionedProject.findMany({ where: { projectId: data.project_id, - neonClientId: data.neon_client_id, + externalProjectId: data.external_project_id, }, }); if (provisionedProjects.length === 0) throw new StatusError(400, "The project to transfer was not provisioned by Neon or has already been transferred."); @@ -48,7 +48,7 @@ export const neonIntegrationProjectTransferCodeHandler = createVerificationCodeH const provisionedProject = await tx.provisionedProject.deleteMany({ where: { projectId: data.project_id, - neonClientId: data.neon_client_id, + externalProjectId: data.external_project_id, }, }); diff --git a/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/route.tsx b/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/route.tsx index e8bc03e84..8bb272b22 100644 --- a/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/route.tsx +++ b/apps/backend/src/app/api/latest/integrations/custom/projects/transfer/route.tsx @@ -6,7 +6,7 @@ import { neonAuthorizationHeaderSchema, urlSchema, yupNumber, yupObject, yupStri import { getEnvVariable } from "@stackframe/stack-shared/dist/utils/env"; import { StatusError, throwErr } from "@stackframe/stack-shared/dist/utils/errors"; import { decodeBasicAuthorizationHeader } from "@stackframe/stack-shared/dist/utils/http"; -import { neonIntegrationProjectTransferCodeHandler } from "./confirm/verification-code-handler"; +import { integrationProjectTransferCodeHandler } from "./confirm/verification-code-handler"; async function validateAndGetTransferInfo(authorizationHeader: string, projectId: string) { const [clientId, clientSecret] = decodeBasicAuthorizationHeader(authorizationHeader)!; @@ -15,7 +15,7 @@ async function validateAndGetTransferInfo(authorizationHeader: string, projectId const provisionedProject = await prismaClient.provisionedProject.findUnique({ where: { projectId, - neonClientId: clientId, + externalProjectId: clientId, }, }); if (!provisionedProject) { @@ -84,12 +84,12 @@ export const POST = createSmartRouteHandler({ handler: async (req) => { const { provisionedProject } = await validateAndGetTransferInfo(req.headers.authorization[0], req.body.project_id); - const transferCodeObj = await neonIntegrationProjectTransferCodeHandler.createCode({ + const transferCodeObj = await integrationProjectTransferCodeHandler.createCode({ tenancy: await getSoleTenancyFromProjectBranch("internal", DEFAULT_BRANCH_ID), method: {}, data: { project_id: provisionedProject.projectId, - neon_client_id: provisionedProject.neonClientId, + external_project_id: provisionedProject.externalProjectId, }, callbackUrl: new URL("/integrations/custom/projects/transfer/confirm", getEnvVariable("NEXT_PUBLIC_STACK_DASHBOARD_URL")), expiresInMs: 1000 * 60 * 60, diff --git a/apps/backend/src/app/api/latest/integrations/idp.ts b/apps/backend/src/app/api/latest/integrations/idp.ts index 311d3a7a3..5f4d63faf 100644 --- a/apps/backend/src/app/api/latest/integrations/idp.ts +++ b/apps/backend/src/app/api/latest/integrations/idp.ts @@ -367,13 +367,13 @@ export async function createOidcProvider(options: { id: string, baseUrl: string, if (typeof state !== 'string') { throwErr(`state is not a string`); } - let neonProjectName: string | undefined; + let externalProjectName: string | undefined; try { const base64Decoded = new TextDecoder().decode(decodeBase64OrBase64Url(state)); const json = JSON.parse(base64Decoded); - neonProjectName = json?.details?.neon_project_name; - if (typeof neonProjectName !== 'string') { - throwErr(`neon_project_name is not a string`, { type: typeof neonProjectName, neonProjectName }); + externalProjectName = json?.details?.external_project_name ?? json?.details?.neon_project_name; + if (typeof externalProjectName !== 'string') { + throwErr(`external_project_name is not a string`, { type: typeof externalProjectName, externalProjectName }); } } catch (e) { // this probably shouldn't happen, because it means Neon messed up the configuration @@ -385,8 +385,8 @@ export async function createOidcProvider(options: { id: string, baseUrl: string, const uid = ctx.path.split('/')[2]; const interactionUrl = new URL(options.clientInteractionUrl); interactionUrl.searchParams.set("interaction_uid", uid); - if (neonProjectName) { - interactionUrl.searchParams.set("neon_project_name", neonProjectName); + if (externalProjectName) { + interactionUrl.searchParams.set("external_project_name", externalProjectName); } return ctx.redirect(interactionUrl.toString()); } diff --git a/apps/backend/src/app/api/latest/integrations/neon/internal/confirm/route.tsx b/apps/backend/src/app/api/latest/integrations/neon/internal/confirm/route.tsx index 13b46047a..f26e55398 100644 --- a/apps/backend/src/app/api/latest/integrations/neon/internal/confirm/route.tsx +++ b/apps/backend/src/app/api/latest/integrations/neon/internal/confirm/route.tsx @@ -18,7 +18,7 @@ export const POST = createSmartRouteHandler({ body: yupObject({ interaction_uid: yupString().defined(), project_id: yupString().defined(), - neon_project_name: yupString().optional(), + external_project_name: yupString().optional(), }).defined(), }), response: yupObject({ @@ -33,7 +33,7 @@ export const POST = createSmartRouteHandler({ const set = await prismaClient.apiKeySet.create({ data: { projectId: req.body.project_id, - description: `Auto-generated for Neon${req.body.neon_project_name ? ` (${req.body.neon_project_name})` : ""}`, + description: `Auto-generated for ${req.body.external_project_name ? `"${req.body.external_project_name}"` : "an external project"}`, expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365 * 100), superSecretAdminKey: `sak_${generateSecureRandomString()}`, }, diff --git a/apps/backend/src/app/api/latest/integrations/neon/projects/provision/route.tsx b/apps/backend/src/app/api/latest/integrations/neon/projects/provision/route.tsx index 79f7a22ff..c454ac285 100644 --- a/apps/backend/src/app/api/latest/integrations/neon/projects/provision/route.tsx +++ b/apps/backend/src/app/api/latest/integrations/neon/projects/provision/route.tsx @@ -54,7 +54,7 @@ export const POST = createSmartRouteHandler({ await prismaClient.provisionedProject.create({ data: { projectId: createdProject.id, - neonClientId: clientId, + externalProjectId: clientId, }, }); diff --git a/apps/backend/src/app/api/latest/integrations/neon/projects/transfer/confirm/verification-code-handler.tsx b/apps/backend/src/app/api/latest/integrations/neon/projects/transfer/confirm/verification-code-handler.tsx index 32a1ad2d2..236839903 100644 --- a/apps/backend/src/app/api/latest/integrations/neon/projects/transfer/confirm/verification-code-handler.tsx +++ b/apps/backend/src/app/api/latest/integrations/neon/projects/transfer/confirm/verification-code-handler.tsx @@ -34,7 +34,7 @@ export const neonIntegrationProjectTransferCodeHandler = createVerificationCodeH const provisionedProjects = await prismaClient.provisionedProject.findMany({ where: { projectId: data.project_id, - neonClientId: data.neon_client_id, + externalProjectId: data.neon_client_id, }, }); if (provisionedProjects.length === 0) throw new StatusError(400, "The project to transfer was not provisioned by Neon or has already been transferred."); @@ -48,7 +48,7 @@ export const neonIntegrationProjectTransferCodeHandler = createVerificationCodeH const provisionedProject = await tx.provisionedProject.deleteMany({ where: { projectId: data.project_id, - neonClientId: data.neon_client_id, + externalProjectId: data.neon_client_id, }, }); diff --git a/apps/backend/src/app/api/latest/integrations/neon/projects/transfer/route.tsx b/apps/backend/src/app/api/latest/integrations/neon/projects/transfer/route.tsx index cf9edfa56..79ccceaa6 100644 --- a/apps/backend/src/app/api/latest/integrations/neon/projects/transfer/route.tsx +++ b/apps/backend/src/app/api/latest/integrations/neon/projects/transfer/route.tsx @@ -15,7 +15,7 @@ async function validateAndGetTransferInfo(authorizationHeader: string, projectId const provisionedProject = await prismaClient.provisionedProject.findUnique({ where: { projectId, - neonClientId: clientId, + externalProjectId: clientId, }, }); if (!provisionedProject) { @@ -89,7 +89,7 @@ export const POST = createSmartRouteHandler({ method: {}, data: { project_id: provisionedProject.projectId, - neon_client_id: provisionedProject.neonClientId, + neon_client_id: provisionedProject.externalProjectId, }, callbackUrl: new URL("/integrations/neon/projects/transfer/confirm", getEnvVariable("NEXT_PUBLIC_STACK_DASHBOARD_URL")), expiresInMs: 1000 * 60 * 60, diff --git a/apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/oauth.test.ts b/apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/oauth.test.ts index 022ec99b4..0151e0f39 100644 --- a/apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/oauth.test.ts +++ b/apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/oauth.test.ts @@ -12,7 +12,7 @@ async function authorizePart1(redirectUri: string = "http://localhost:30000/api/ response_type: "code", client_id: "custom-local", redirect_uri: redirectUri, - state: encodeBase64Url(new TextEncoder().encode(JSON.stringify({ details: { neon_project_name: 'custom-project' } }))), + state: encodeBase64Url(new TextEncoder().encode(JSON.stringify({ details: { external_project_name: 'custom-project' } }))), code_challenge: "xf6HY7PIgoaCf_eMniSt-45brYE2J_05C9BnfIbueik", code_challenge_method: "S256", }, @@ -95,7 +95,7 @@ async function authorize(projectId: string) { "status": 307, "body": "http://localhost:8101/integrations/custom/confirm?interaction_uid=%3Cstripped+query+param%3E&=", "headers": Headers { - "location": "http://localhost:8101/integrations/custom/confirm?interaction_uid=%3Cstripped+query+param%3E&neon_project_name=custom-project", + "location": "http://localhost:8101/integrations/custom/confirm?interaction_uid=%3Cstripped+query+param%3E&external_project_name=custom-project",