Skip to content

Commit 9762bbc

Browse files
authored
fix(wand): validate session before allowing access to wand generation (#2383)
* fix(wand): validate session before allowing access to wand generation * ack PR comment * ack PR comments
1 parent e43afc8 commit 9762bbc

File tree

1 file changed

+37
-1
lines changed

1 file changed

+37
-1
lines changed

apps/sim/app/api/wand/route.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ import { userStats, workflow } from '@sim/db/schema'
33
import { eq, sql } from 'drizzle-orm'
44
import { type NextRequest, NextResponse } from 'next/server'
55
import OpenAI, { AzureOpenAI } from 'openai'
6+
import { getSession } from '@/lib/auth'
67
import { checkAndBillOverageThreshold } from '@/lib/billing/threshold-billing'
78
import { env } from '@/lib/core/config/env'
89
import { getCostMultiplier, isBillingEnabled } from '@/lib/core/config/feature-flags'
910
import { generateRequestId } from '@/lib/core/utils/request'
1011
import { createLogger } from '@/lib/logs/console/logger'
12+
import { verifyWorkspaceMembership } from '@/app/api/workflows/utils'
1113
import { getModelPricing } from '@/providers/utils'
1214

1315
export const dynamic = 'force-dynamic'
@@ -135,7 +137,6 @@ async function updateUserStatsForWand(
135137
costAdded: costToStore,
136138
})
137139

138-
// Check if user has hit overage threshold and bill incrementally
139140
await checkAndBillOverageThreshold(userId)
140141
} catch (error) {
141142
logger.error(`[${requestId}] Failed to update user stats for wand usage`, error)
@@ -146,6 +147,12 @@ export async function POST(req: NextRequest) {
146147
const requestId = generateRequestId()
147148
logger.info(`[${requestId}] Received wand generation request`)
148149

150+
const session = await getSession()
151+
if (!session?.user?.id) {
152+
logger.warn(`[${requestId}] Unauthorized wand generation attempt`)
153+
return NextResponse.json({ success: false, error: 'Unauthorized' }, { status: 401 })
154+
}
155+
149156
if (!client) {
150157
logger.error(`[${requestId}] AI client not initialized. Missing API key.`)
151158
return NextResponse.json(
@@ -167,6 +174,35 @@ export async function POST(req: NextRequest) {
167174
)
168175
}
169176

177+
if (workflowId) {
178+
const [workflowRecord] = await db
179+
.select({ workspaceId: workflow.workspaceId, userId: workflow.userId })
180+
.from(workflow)
181+
.where(eq(workflow.id, workflowId))
182+
.limit(1)
183+
184+
if (!workflowRecord) {
185+
logger.warn(`[${requestId}] Workflow not found: ${workflowId}`)
186+
return NextResponse.json({ success: false, error: 'Workflow not found' }, { status: 404 })
187+
}
188+
189+
if (workflowRecord.workspaceId) {
190+
const permission = await verifyWorkspaceMembership(
191+
session.user.id,
192+
workflowRecord.workspaceId
193+
)
194+
if (!permission || (permission !== 'admin' && permission !== 'write')) {
195+
logger.warn(
196+
`[${requestId}] User ${session.user.id} does not have write access to workspace for workflow ${workflowId}`
197+
)
198+
return NextResponse.json({ success: false, error: 'Unauthorized' }, { status: 403 })
199+
}
200+
} else if (workflowRecord.userId !== session.user.id) {
201+
logger.warn(`[${requestId}] User ${session.user.id} does not own workflow ${workflowId}`)
202+
return NextResponse.json({ success: false, error: 'Unauthorized' }, { status: 403 })
203+
}
204+
}
205+
170206
const finalSystemPrompt =
171207
systemPrompt ||
172208
'You are a helpful AI assistant. Generate content exactly as requested by the user.'

0 commit comments

Comments
 (0)