From 61742bc0455bff03ec73b2e32ffb4b40b168759b Mon Sep 17 00:00:00 2001 From: Jack <19261047+MrMushrooooom@users.noreply.github.com> Date: Sun, 16 Aug 2026 17:53:12 +0000 Subject: [PATCH] feat(console): restore referral rewards --- .../actions/restore-referral-reward.ts | 24 ++++++++++++++ packages/console/core/src/referral.ts | 32 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 packages/console/app/src/routes/api/support/actions/restore-referral-reward.ts diff --git a/packages/console/app/src/routes/api/support/actions/restore-referral-reward.ts b/packages/console/app/src/routes/api/support/actions/restore-referral-reward.ts new file mode 100644 index 000000000000..43e33a0239f0 --- /dev/null +++ b/packages/console/app/src/routes/api/support/actions/restore-referral-reward.ts @@ -0,0 +1,24 @@ +import type { APIEvent } from "@solidjs/start/server" +import { Referral } from "@opencode-ai/console-core/referral.js" +import { safeEqual } from "@opencode-ai/console-core/util/crypto.js" +import { Resource } from "@opencode-ai/console-resource" +import z from "zod" + +const Body = z.object({ + workspaceID: z.string().startsWith("wrk_"), + referralID: z.string().startsWith("ref_"), +}) + +export async function POST(event: APIEvent) { + if (!safeEqual(event.request.headers.get("authorization") ?? "", `Bearer ${Resource.SUPPORT_API_KEY.value}`)) { + return Response.json({ error: "Unauthorized" }, { status: 401 }) + } + + const body = Body.safeParse(await event.request.json().catch(() => undefined)) + if (!body.success) { + return Response.json({ error: "Invalid request", issues: body.error.issues }, { status: 400 }) + } + return Referral.restoreReward(body.data) + .then((result) => Response.json({ success: true, message: "Referral reward restored", result })) + .catch((error) => Response.json({ error: error instanceof Error ? error.message : String(error) }, { status: 400 })) +} diff --git a/packages/console/core/src/referral.ts b/packages/console/core/src/referral.ts index 7d683f8d88a8..8f0236109573 100644 --- a/packages/console/core/src/referral.ts +++ b/packages/console/core/src/referral.ts @@ -475,6 +475,38 @@ export namespace Referral { }) } + export async function restoreReward(input: { workspaceID: string; referralID: string }) { + return Database.transaction(async (tx) => { + const reward = await tx + .select({ timeApplied: ReferralRewardTable.timeApplied }) + .from(ReferralRewardTable) + .innerJoin(ReferralTable, eq(ReferralTable.id, ReferralRewardTable.referralID)) + .where( + and( + eq(ReferralRewardTable.workspaceID, input.workspaceID), + eq(ReferralRewardTable.referralID, input.referralID), + isNull(ReferralRewardTable.timeDeleted), + isNull(ReferralTable.timeDeleted), + ), + ) + .then((rows) => rows[0]) + if (!reward) throw new Error("Referral reward not found") + + await tx + .update(ReferralRewardTable) + .set({ timeApplied: null }) + .where( + and( + eq(ReferralRewardTable.workspaceID, input.workspaceID), + eq(ReferralRewardTable.referralID, input.referralID), + isNull(ReferralRewardTable.timeDeleted), + ), + ) + + return { restored: reward.timeApplied !== null } + }) + } + export async function completeFromLiteSubscription(input: { workspaceID: string; userID: string }) { return Database.transaction(async (tx) => { const invitee = await tx