summaryrefslogtreecommitdiff
path: root/apps/web/src/app
diff options
context:
space:
mode:
authorAhmet Kilinc <akx9@icloud.com>2025-07-16 01:00:40 +0100
committerAhmet Kilinc <akx9@icloud.com>2025-07-16 01:00:40 +0100
commiteb49500592e5c50c5637c09ea585b065545f2135 (patch)
tree8cf0df336f2af737ef775c516c1f3380b418bc7e /apps/web/src/app
parent5178732c4c1205698d1846dd82896d9342558ac6 (diff)
downloadopencut-eb49500592e5c50c5637c09ea585b065545f2135.tar.gz
adds Vercel BotId
Diffstat (limited to 'apps/web/src/app')
-rw-r--r--apps/web/src/app/api/waitlist/route.ts7
-rw-r--r--apps/web/src/app/layout.tsx11
2 files changed, 18 insertions, 0 deletions
diff --git a/apps/web/src/app/api/waitlist/route.ts b/apps/web/src/app/api/waitlist/route.ts
index 4d64be77..031ebd5a 100644
--- a/apps/web/src/app/api/waitlist/route.ts
+++ b/apps/web/src/app/api/waitlist/route.ts
@@ -1,6 +1,7 @@
import { NextRequest, NextResponse } from "next/server";
import { db, eq } from "@opencut/db";
import { waitlist } from "@opencut/db/schema";
+import { checkBotId } from "botid/server";
import { nanoid } from "nanoid";
import { waitlistRateLimit } from "@/lib/rate-limit";
import { z } from "zod";
@@ -143,6 +144,12 @@ async function validateCSRFToken(request: NextRequest): Promise<boolean> {
}
export async function POST(request: NextRequest) {
+ const verification = await checkBotId();
+
+ if (verification.isBot) {
+ return NextResponse.json({ error: "Access denied" }, { status: 403 });
+ }
+
const identifier = request.headers.get("x-forwarded-for") ?? "127.0.0.1";
const { success } = await waitlistRateLimit.limit(identifier);
diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx
index 9ac54262..1cbc3f2e 100644
--- a/apps/web/src/app/layout.tsx
+++ b/apps/web/src/app/layout.tsx
@@ -7,9 +7,17 @@ import { TooltipProvider } from "../components/ui/tooltip";
import { StorageProvider } from "../components/storage-provider";
import { baseMetaData } from "./metadata";
import { defaultFont } from "../lib/font-config";
+import { BotIdClient } from "botid/client";
export const metadata = baseMetaData;
+const protectedRoutes = [
+ {
+ path: "/api/waitlist",
+ method: "POST",
+ },
+];
+
export default function RootLayout({
children,
}: Readonly<{
@@ -17,6 +25,9 @@ export default function RootLayout({
}>) {
return (
<html lang="en" suppressHydrationWarning>
+ <head>
+ <BotIdClient protect={protectedRoutes} />
+ </head>
<body className={`${defaultFont.className} font-sans antialiased`}>
<ThemeProvider attribute="class" forcedTheme="dark">
<TooltipProvider>