From 53827506a38ac0799312d0dbca87f66f63343b98 Mon Sep 17 00:00:00 2001 From: OpenClaw Date: Fri, 6 Mar 2026 17:52:20 +0000 Subject: [PATCH] auto(agent): added deal existence check and duplicate review prevention in reviews.js --- backend/src/routes/reviews.js | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/backend/src/routes/reviews.js b/backend/src/routes/reviews.js index 3f0f2db..5c4a7c4 100644 --- a/backend/src/routes/reviews.js +++ b/backend/src/routes/reviews.js @@ -8,11 +8,15 @@ const router = Router(); router.post('/:dealId', requireAuth, async (req, res) => { try { const dealId = Number(req.params.dealId); - const parsed = z.object({ + + // Input validation with Zod + const reviewSchema = z.object({ revieweeId: z.number().int().positive(), rating: z.number().int().min(1).max(5), comment: z.string().max(2000).optional() - }).safeParse(req.body); + }); + + const parsed = reviewSchema.safeParse(req.body); if (!parsed.success || Number.isNaN(dealId)) { return res.status(400).json({ error: 'Invalid payload' }); @@ -24,6 +28,26 @@ router.post('/:dealId', requireAuth, async (req, res) => { const { revieweeId, rating, comment } = parsed.data; + // Check if deal exists + const [dealResult] = await pool.query( + 'SELECT id FROM deals WHERE id = ?', + [dealId] + ); + + if (dealResult.length === 0) { + return res.status(404).json({ error: 'Deal not found' }); + } + + // Check if user has already reviewed this deal + const [existingReview] = await pool.query( + 'SELECT id FROM reviews WHERE deal_id = ? AND reviewer_id = ?', + [dealId, req.user.userId] + ); + + if (existingReview.length > 0) { + return res.status(409).json({ error: 'You have already reviewed this deal' }); + } + const [result] = await pool.query( `INSERT INTO reviews (deal_id, reviewer_id, reviewee_id, rating, comment, earliest_prompt_at, latest_prompt_at) VALUES (?, ?, ?, ?, ?, ?, ?)`,