From d70e8422125fcbe99dedbed8cab3dd2fc51890d1 Mon Sep 17 00:00:00 2001 From: Sahaj Jain Date: Sun, 4 May 2025 05:07:20 +0530 Subject: [PATCH] add server-side auth for ai theme and fix save action --- app/api/generate-theme/route.ts | 14 ++++++++++++-- components/editor/action-bar/action-bar.tsx | 10 +++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/app/api/generate-theme/route.ts b/app/api/generate-theme/route.ts index ff0972ed..e17efe67 100644 --- a/app/api/generate-theme/route.ts +++ b/app/api/generate-theme/route.ts @@ -3,10 +3,12 @@ import { createFallback } from "ai-fallback"; import { generateObject } from "ai"; import { z } from "zod"; import { themeStylePropsSchema } from "@/types/theme"; -import kv from "@vercel/kv"; +import { kv } from "@vercel/kv"; import { Ratelimit } from "@upstash/ratelimit"; import { NextRequest } from "next/server"; import { createGoogleGenerativeAI } from "@ai-sdk/google"; +import { auth } from "@/lib/auth"; + const requestSchema = z.object({ prompt: z.string().min(1), }); @@ -30,6 +32,13 @@ const ratelimit = new Ratelimit({ export async function POST(req: NextRequest) { try { + const session = await auth.api.getSession(req); + if (!session) { + return new Response("Unauthorized", { + status: 401, + }); + } + // Apply rate limiting based on the request IP const ip = req.headers.get("x-forwarded-for") ?? "anonymous"; const { success } = await ratelimit.limit(ip); @@ -69,7 +78,8 @@ export async function POST(req: NextRequest) { system: `You are an AI generating Shadcn UI color themes. Input: User description or existing theme tokens. Format: Use Hex values (#000000) exclusively for colors. -Requirement: Ensure light/dark mode cohesion. If asked to change the theme's main color (e.g., "make it green"), adjust related colors (--accent, --secondary, --ring, --border) along with --primary to create a cohesive new palette.`, +Requirement: Ensure light/dark mode cohesion. If asked to change the theme's main color (e.g., "make it green"), adjust related colors (--accent, --secondary, --ring, --border) along with --primary to create a cohesive new palette. +Ensure sufficient contrast between foreground and background colors.`, prompt: `Generate Shadcn theme. Input: ${prompt}`, }); diff --git a/components/editor/action-bar/action-bar.tsx b/components/editor/action-bar/action-bar.tsx index 5411eeae..562bb5f4 100644 --- a/components/editor/action-bar/action-bar.tsx +++ b/components/editor/action-bar/action-bar.tsx @@ -99,17 +99,17 @@ export function ActionBar() { }); }; - const handleSaveClick = (shareAfterSave: boolean = false) => { + const handleSaveClick = (options?: { shareAfterSave?: boolean }) => { if (!session) { openAuthDialog( "signin", - shareAfterSave ? "SAVE_THEME_FOR_SHARE" : "SAVE_THEME" + options?.shareAfterSave ? "SAVE_THEME_FOR_SHARE" : "SAVE_THEME" ); return; } setSaveDialogOpen(true); - if (shareAfterSave) { + if (options?.shareAfterSave) { setShareAfterSave(true); } }; @@ -146,7 +146,7 @@ export function ActionBar() { const handleShareClick = async (id?: string) => { if (hasThemeChangedFromCheckpoint()) { - handleSaveClick(true); + handleSaveClick({ shareAfterSave: true }); return; } @@ -181,7 +181,7 @@ export function ActionBar() { setCssImportOpen(true)} onCodeClick={() => setCodePanelOpen(true)} - onSaveClick={handleSaveClick} + onSaveClick={() => handleSaveClick()} onAiGenerateClick={handleAiGenerateClick} isSaving={isCreatingTheme} onShareClick={handleShareClick}