From 822f50779feed31e3ffa492668cd1f385c0175bc Mon Sep 17 00:00:00 2001 From: Steven Tey Date: Fri, 5 Dec 2025 13:26:59 -0800 Subject: [PATCH] Prevent deleting program domains --- apps/web/app/(ee)/api/cron/domains/delete/route.ts | 8 +------- apps/web/app/api/domains/[domain]/route.ts | 14 +++++++++++++- apps/web/lib/api/domains/get-domain-or-throw.ts | 1 + packages/prisma/schema/domain.prisma | 1 + packages/prisma/schema/program.prisma | 3 ++- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/apps/web/app/(ee)/api/cron/domains/delete/route.ts b/apps/web/app/(ee)/api/cron/domains/delete/route.ts index 31d88ed7cb8..d028f2aed58 100644 --- a/apps/web/app/(ee)/api/cron/domains/delete/route.ts +++ b/apps/web/app/(ee)/api/cron/domains/delete/route.ts @@ -24,12 +24,6 @@ export async function POST(req: Request) { await verifyQstashSignature({ req, rawBody }); const { domain } = schema.parse(JSON.parse(rawBody)); - if (domain === "poly.market") { - // temp skip - return new Response( - `Domain ${domain} is not allowed to be deleted. Skipping...`, - ); - } const domainRecord = await prisma.domain.findUnique({ where: { @@ -66,7 +60,7 @@ export async function POST(req: Request) { linkCache.deleteMany(links), // Record link in Tinybird - recordLink(links), + recordLink(links, { deleted: true }), // Remove image from R2 storage if it exists links diff --git a/apps/web/app/api/domains/[domain]/route.ts b/apps/web/app/api/domains/[domain]/route.ts index 7855961438c..f57d16ea037 100644 --- a/apps/web/app/api/domains/[domain]/route.ts +++ b/apps/web/app/api/domains/[domain]/route.ts @@ -223,7 +223,11 @@ export const PATCH = withWorkspace( // DELETE /api/domains/[domain] - delete a workspace's domain export const DELETE = withWorkspace( async ({ params, workspace }) => { - const { slug: domain, registeredDomain } = await getDomainOrThrow({ + const { + slug: domain, + registeredDomain, + partnerProgram, + } = await getDomainOrThrow({ workspace, domain: params.domain, dubDomainChecks: true, @@ -236,6 +240,14 @@ export const DELETE = withWorkspace( }); } + if (partnerProgram) { + throw new DubApiError({ + code: "forbidden", + message: + "You cannot delete a domain that is actively in use in a partner program.", + }); + } + await markDomainAsDeleted({ domain, }); diff --git a/apps/web/lib/api/domains/get-domain-or-throw.ts b/apps/web/lib/api/domains/get-domain-or-throw.ts index bacd15503c7..d0b40c6b8e4 100644 --- a/apps/web/lib/api/domains/get-domain-or-throw.ts +++ b/apps/web/lib/api/domains/get-domain-or-throw.ts @@ -17,6 +17,7 @@ export const getDomainOrThrow = async ({ where: { slug: domain }, include: { registeredDomain: true, + partnerProgram: true, }, }); diff --git a/packages/prisma/schema/domain.prisma b/packages/prisma/schema/domain.prisma index 95360030f3b..5bb19ddbfd5 100644 --- a/packages/prisma/schema/domain.prisma +++ b/packages/prisma/schema/domain.prisma @@ -21,6 +21,7 @@ model Domain { project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade) links Link[] registeredDomain RegisteredDomain? + partnerProgram Program? @@index(projectId) @@index(lastChecked(sort: Asc)) diff --git a/packages/prisma/schema/program.prisma b/packages/prisma/schema/program.prisma index 49ad1e7779a..4d880cb650b 100644 --- a/packages/prisma/schema/program.prisma +++ b/packages/prisma/schema/program.prisma @@ -31,7 +31,7 @@ model Program { defaultGroupId String name String slug String @unique - domain String? + domain String? @unique url String? logo String? // TODO: remove after we refactor all program.logo fields to use group.logo instead primaryRewardEvent EventType @default(sale) @@ -52,6 +52,7 @@ model Program { startedAt DateTime? workspace Project @relation(fields: [workspaceId], references: [id]) + customDomain Domain? @relation(fields: [domain], references: [slug]) partners ProgramEnrollment[] payouts Payout[] invoices Invoice[]