diff --git a/backend/src/routes/addresses.js b/backend/src/routes/addresses.js index 5be09fa..dfca5dc 100644 --- a/backend/src/routes/addresses.js +++ b/backend/src/routes/addresses.js @@ -9,144 +9,75 @@ const router = Router(); const hashCode = (code) => createHash('sha256').update(code).digest('hex'); -// Schema for change request validation -const changeRequestSchema = z.object({ - newAddress: z.string().min(10).max(500) -}); - -// Schema for verification request validation -const verifyRequestSchema = z.object({ - requestId: z.number().int().positive(), - code: z.string().regex(/^\d{6}$/) -}); - router.post('/change-request', requireAuth, async (req, res) => { - try { - const parsed = changeRequestSchema.safeParse(req.body); - if (!parsed.success) { - return res.status(400).json({ - error: 'Invalid input data', - details: parsed.error.flatten() - }); - } + const parsed = z.object({ newAddress: z.string().min(10) }).safeParse(req.body); + if (!parsed.success) return res.status(400).json({ error: parsed.error.flatten() }); - // Check if user already has an address - try { - const [existingRows] = await pool.query( - `SELECT id FROM addresses WHERE user_id = ? LIMIT 1`, - [req.user.userId] - ); + const verificationCode = String(randomInt(100000, 999999)); + const verificationCodeHash = hashCode(verificationCode); - if (existingRows.length === 0) { - return res.status(400).json({ - error: 'User must have an existing address to request a change' - }); - } - } catch (err) { - console.error('Error checking existing address:', err); - return res.status(500).json({ - error: 'Internal server error while checking existing address' - }); - } + const [result] = await pool.query( + `INSERT INTO address_change_requests (user_id, new_address_encrypted, verification_code_hash) + VALUES (?, ?, ?)`, + [req.user.userId, encryptText(parsed.data.newAddress), verificationCodeHash] + ); - const verificationCode = String(randomInt(100000, 999999)); - const verificationCodeHash = hashCode(verificationCode); - - try { - const [result] = await pool.query( - `INSERT INTO address_change_requests (user_id, new_address_encrypted, verification_code_hash) - VALUES (?, ?, ?)`, - [req.user.userId, encryptText(parsed.data.newAddress), verificationCodeHash] - ); - - res.status(201).json({ - requestId: result.insertId, - postalDispatch: 'pending_letter', - note: 'Verification code generated for postal letter dispatch.', - verificationCode - }); - } catch (err) { - console.error('Error in address change request:', err); - return res.status(500).json({ - error: 'Internal server error while processing address change request' - }); - } - } catch (err) { - console.error('Unexpected error in change-request route:', err); - return res.status(500).json({ - error: 'Unexpected internal server error' - }); - } + res.status(201).json({ + requestId: result.insertId, + postalDispatch: 'pending_letter', + note: 'Verification code generated for postal letter dispatch.', + verificationCode + }); }); router.post('/verify', requireAuth, async (req, res) => { - try { - const parsed = verifyRequestSchema.safeParse(req.body); - if (!parsed.success) { - return res.status(400).json({ - error: 'Invalid input data', - details: parsed.error.flatten() - }); - } + const parsed = z.object({ requestId: z.number().int().positive(), code: z.string().regex(/^\d{6}$/) }).safeParse(req.body); + if (!parsed.success) return res.status(400).json({ error: parsed.error.flatten() }); - const { requestId, code } = parsed.data; + const { requestId, code } = parsed.data; - try { - const [rows] = await pool.query( - `SELECT id, user_id, new_address_encrypted, verification_code_hash, status - FROM address_change_requests - WHERE id = ? LIMIT 1`, - [requestId] - ); + const [rows] = await pool.query( + `SELECT id, user_id, new_address_encrypted, verification_code_hash, status + FROM address_change_requests + WHERE id = ? LIMIT 1`, + [requestId] + ); - const request = rows[0]; - if (!request) return res.status(404).json({ error: 'Request not found' }); - if (request.user_id !== req.user.userId) return res.status(403).json({ error: 'Forbidden' }); - if (request.status !== 'pending_letter') return res.status(409).json({ error: 'Request not pending' }); + const request = rows[0]; + if (!request) return res.status(404).json({ error: 'Request not found' }); + if (request.user_id !== req.user.userId) return res.status(403).json({ error: 'Forbidden' }); + if (request.status !== 'pending_letter') return res.status(409).json({ error: 'Request not pending' }); - if (hashCode(code) !== request.verification_code_hash) { - return res.status(400).json({ error: 'Invalid verification code' }); - } - - const conn = await pool.getConnection(); - try { - await conn.beginTransaction(); - - await conn.query( - `UPDATE address_change_requests - SET status = 'verified', verified_at = CURRENT_TIMESTAMP - WHERE id = ?`, - [requestId] - ); - - await conn.query( - `INSERT INTO addresses (user_id, address_encrypted, postal_verified_at) - VALUES (?, ?, CURRENT_TIMESTAMP)`, - [req.user.userId, request.new_address_encrypted] - ); - - await conn.commit(); - } catch (err) { - await conn.rollback(); - console.error('Error in address verification transaction:', err); - throw err; - } finally { - conn.release(); - } - - res.json({ status: 'verified' }); - } catch (err) { - console.error('Error in address verification:', err); - return res.status(500).json({ - error: 'Internal server error while verifying address' - }); - } - } catch (err) { - console.error('Unexpected error in verify route:', err); - return res.status(500).json({ - error: 'Unexpected internal server error' - }); + if (hashCode(code) !== request.verification_code_hash) { + return res.status(400).json({ error: 'Invalid verification code' }); } + + const conn = await pool.getConnection(); + try { + await conn.beginTransaction(); + + await conn.query( + `UPDATE address_change_requests + SET status = 'verified', verified_at = CURRENT_TIMESTAMP + WHERE id = ?`, + [requestId] + ); + + await conn.query( + `INSERT INTO addresses (user_id, address_encrypted, postal_verified_at) + VALUES (?, ?, CURRENT_TIMESTAMP)`, + [req.user.userId, request.new_address_encrypted] + ); + + await conn.commit(); + } catch (err) { + await conn.rollback(); + throw err; + } finally { + conn.release(); + } + + res.json({ status: 'verified' }); }); -export default router; \ No newline at end of file +export default router; diff --git a/backend/src/routes/auth.js b/backend/src/routes/auth.js index 6bb8714..67d93ab 100644 --- a/backend/src/routes/auth.js +++ b/backend/src/routes/auth.js @@ -12,51 +12,14 @@ const registerSchema = z.object({ displayName: z.string().min(2).max(120) }); -const loginSchema = z.object({ - email: z.string().email(), - password: z.string().min(1) -}); +router.post('/register', async (req, res) => { + const parsed = registerSchema.safeParse(req.body); + if (!parsed.success) return res.status(400).json({ error: parsed.error.flatten() }); + + const { email, password, displayName } = parsed.data; + const passwordHash = await bcrypt.hash(password, 12); -// Middleware für Validierung -const validateRegister = (req, res, next) => { try { - const parsed = registerSchema.safeParse(req.body); - if (!parsed.success) { - return res.status(400).json({ - error: 'Validation failed', - details: parsed.error.flatten() - }); - } - req.validatedData = parsed.data; - next(); - } catch (err) { - console.error('Validation error:', err); - return res.status(500).json({ error: 'Internal server error during validation' }); - } -}; - -const validateLogin = (req, res, next) => { - try { - const parsed = loginSchema.safeParse(req.body); - if (!parsed.success) { - return res.status(400).json({ - error: 'Validation failed', - details: parsed.error.flatten() - }); - } - req.validatedData = parsed.data; - next(); - } catch (err) { - console.error('Validation error:', err); - return res.status(500).json({ error: 'Internal server error during validation' }); - } -}; - -router.post('/register', validateRegister, async (req, res) => { - try { - const { email, password, displayName } = req.validatedData; - const passwordHash = await bcrypt.hash(password, 12); - const [result] = await pool.query( 'INSERT INTO users (email, password_hash, display_name) VALUES (?, ?, ?)', [email, passwordHash, displayName] @@ -65,35 +28,26 @@ router.post('/register', validateRegister, async (req, res) => { const token = jwt.sign({ userId: result.insertId, email }, process.env.JWT_SECRET, { expiresIn: '7d' }); return res.status(201).json({ token }); } catch (err) { - console.error('Registration error:', err); - if (err.code === 'ER_DUP_ENTRY') { - return res.status(409).json({ error: 'Email already exists' }); - } + if (err.code === 'ER_DUP_ENTRY') return res.status(409).json({ error: 'Email already exists' }); return res.status(500).json({ error: 'Registration failed' }); } }); -router.post('/login', validateLogin, async (req, res) => { - try { - const { email, password } = req.validatedData; - const [rows] = await pool.query('SELECT id, email, password_hash FROM users WHERE email = ? LIMIT 1', [email]); - const user = rows[0]; +router.post('/login', async (req, res) => { + const parsed = z.object({ email: z.string().email(), password: z.string().min(1) }).safeParse(req.body); + if (!parsed.success) return res.status(400).json({ error: parsed.error.flatten() }); - if (!user) { - return res.status(401).json({ error: 'Invalid credentials' }); - } + const { email, password } = parsed.data; + const [rows] = await pool.query('SELECT id, email, password_hash FROM users WHERE email = ? LIMIT 1', [email]); + const user = rows[0]; - const ok = await bcrypt.compare(password, user.password_hash); - if (!ok) { - return res.status(401).json({ error: 'Invalid credentials' }); - } + if (!user) return res.status(401).json({ error: 'Invalid credentials' }); - const token = jwt.sign({ userId: user.id, email: user.email }, process.env.JWT_SECRET, { expiresIn: '7d' }); - return res.status(200).json({ token }); - } catch (err) { - console.error('Login error:', err); - return res.status(500).json({ error: 'Login failed' }); - } + const ok = await bcrypt.compare(password, user.password_hash); + if (!ok) return res.status(401).json({ error: 'Invalid credentials' }); + + const token = jwt.sign({ userId: user.id, email: user.email }, process.env.JWT_SECRET, { expiresIn: '7d' }); + return res.json({ token }); }); -export default router; \ No newline at end of file +export default router; diff --git a/backend/src/routes/contacts.js b/backend/src/routes/contacts.js index db4080b..3a7a246 100644 --- a/backend/src/routes/contacts.js +++ b/backend/src/routes/contacts.js @@ -6,145 +6,92 @@ import { requireAuth } from '../middleware/auth.js'; const router = Router(); const getDealParticipants = async (dealId) => { - try { - const [rows] = await pool.query( - `SELECT d.id, hr.requester_id, o.helper_id - FROM deals d - JOIN help_requests hr ON hr.id = d.request_id - JOIN offers o ON o.id = d.offer_id - WHERE d.id = ? LIMIT 1`, - [dealId] - ); + const [rows] = await pool.query( + `SELECT d.id, hr.requester_id, o.helper_id + FROM deals d + JOIN help_requests hr ON hr.id = d.request_id + JOIN offers o ON o.id = d.offer_id + WHERE d.id = ? LIMIT 1`, + [dealId] + ); - return rows[0] || null; - } catch (error) { - throw new Error('Database error while fetching deal participants'); - } + return rows[0] || null; }; router.post('/request', requireAuth, async (req, res) => { - try { - const parsed = z.object({ - dealId: z.number().int().positive(), - targetUserId: z.number().int().positive() - }).safeParse(req.body); - - if (!parsed.success) { - return res.status(400).json({ error: 'Invalid input data', details: parsed.error.flatten() }); - } + const parsed = z.object({ dealId: z.number().int().positive(), targetUserId: z.number().int().positive() }).safeParse(req.body); + if (!parsed.success) return res.status(400).json({ error: parsed.error.flatten() }); - const { dealId, targetUserId } = parsed.data; - const deal = await getDealParticipants(dealId); - - if (!deal) { - return res.status(404).json({ error: 'Deal not found' }); - } + const { dealId, targetUserId } = parsed.data; + const deal = await getDealParticipants(dealId); + if (!deal) return res.status(404).json({ error: 'Deal not found' }); - const participants = [deal.requester_id, deal.helper_id]; - - if (!participants.includes(req.user.userId) || !participants.includes(targetUserId) || req.user.userId === targetUserId) { - return res.status(403).json({ error: 'Forbidden' }); - } - - const [existing] = await pool.query( - `SELECT id FROM contact_exchange_requests - WHERE deal_id = ? AND requester_id = ? AND target_id = ? LIMIT 1`, - [dealId, req.user.userId, targetUserId] - ); - - if (existing.length) { - return res.status(409).json({ error: 'Request already exists' }); - } - - const [result] = await pool.query( - `INSERT INTO contact_exchange_requests (deal_id, requester_id, target_id, accepted) - VALUES (?, ?, ?, FALSE)`, - [dealId, req.user.userId, targetUserId] - ); - - res.status(201).json({ id: result.insertId }); - } catch (error) { - console.error('Error in contacts request route:', error); - res.status(500).json({ error: 'Internal server error' }); + const participants = [deal.requester_id, deal.helper_id]; + if (!participants.includes(req.user.userId) || !participants.includes(targetUserId) || req.user.userId === targetUserId) { + return res.status(403).json({ error: 'Forbidden' }); } + + const [existing] = await pool.query( + `SELECT id FROM contact_exchange_requests + WHERE deal_id = ? AND requester_id = ? AND target_id = ? LIMIT 1`, + [dealId, req.user.userId, targetUserId] + ); + if (existing.length) return res.status(409).json({ error: 'Request already exists' }); + + const [result] = await pool.query( + `INSERT INTO contact_exchange_requests (deal_id, requester_id, target_id, accepted) + VALUES (?, ?, ?, FALSE)`, + [dealId, req.user.userId, targetUserId] + ); + + res.status(201).json({ id: result.insertId }); }); router.post('/respond', requireAuth, async (req, res) => { - try { - const parsed = z.object({ - requestId: z.number().int().positive(), - accept: z.boolean() - }).safeParse(req.body); - - if (!parsed.success) { - return res.status(400).json({ error: 'Invalid input data', details: parsed.error.flatten() }); - } + const parsed = z.object({ requestId: z.number().int().positive(), accept: z.boolean() }).safeParse(req.body); + if (!parsed.success) return res.status(400).json({ error: parsed.error.flatten() }); - const { requestId, accept } = parsed.data; - const [rows] = await pool.query( - `SELECT id, target_id FROM contact_exchange_requests WHERE id = ? LIMIT 1`, - [requestId] - ); + const { requestId, accept } = parsed.data; + const [rows] = await pool.query( + `SELECT id, target_id FROM contact_exchange_requests WHERE id = ? LIMIT 1`, + [requestId] + ); - const row = rows[0]; - - if (!row) { - return res.status(404).json({ error: 'Request not found' }); - } - - if (row.target_id !== req.user.userId) { - return res.status(403).json({ error: 'Forbidden' }); - } + const row = rows[0]; + if (!row) return res.status(404).json({ error: 'Request not found' }); + if (row.target_id !== req.user.userId) return res.status(403).json({ error: 'Forbidden' }); - if (accept) { - await pool.query('UPDATE contact_exchange_requests SET accepted = TRUE WHERE id = ?', [requestId]); - return res.json({ status: 'accepted' }); - } - - await pool.query('DELETE FROM contact_exchange_requests WHERE id = ?', [requestId]); - res.json({ status: 'rejected' }); - } catch (error) { - console.error('Error in contacts respond route:', error); - res.status(500).json({ error: 'Internal server error' }); + if (accept) { + await pool.query('UPDATE contact_exchange_requests SET accepted = TRUE WHERE id = ?', [requestId]); + return res.json({ status: 'accepted' }); } + + await pool.query('DELETE FROM contact_exchange_requests WHERE id = ?', [requestId]); + res.json({ status: 'rejected' }); }); router.get('/deal/:dealId', requireAuth, async (req, res) => { - try { - const dealId = Number(req.params.dealId); - - if (Number.isNaN(dealId)) { - return res.status(400).json({ error: 'Invalid dealId' }); - } + const dealId = Number(req.params.dealId); + if (Number.isNaN(dealId)) return res.status(400).json({ error: 'Invalid dealId' }); - const deal = await getDealParticipants(dealId); - - if (!deal) { - return res.status(404).json({ error: 'Deal not found' }); - } + const deal = await getDealParticipants(dealId); + if (!deal) return res.status(404).json({ error: 'Deal not found' }); - const participants = [deal.requester_id, deal.helper_id]; - - if (!participants.includes(req.user.userId)) { - return res.status(403).json({ error: 'Forbidden' }); - } + const participants = [deal.requester_id, deal.helper_id]; + if (!participants.includes(req.user.userId)) return res.status(403).json({ error: 'Forbidden' }); - const [rows] = await pool.query( - `SELECT cer.id, cer.requester_id, cer.target_id, cer.accepted, - ru.phone_encrypted AS requester_phone_encrypted, - tu.phone_encrypted AS target_phone_encrypted - FROM contact_exchange_requests cer - JOIN users ru ON ru.id = cer.requester_id - JOIN users tu ON tu.id = cer.target_id - WHERE cer.deal_id = ? AND cer.accepted = TRUE`, - [dealId] - ); + const [rows] = await pool.query( + `SELECT cer.id, cer.requester_id, cer.target_id, cer.accepted, + ru.phone_encrypted AS requester_phone_encrypted, + tu.phone_encrypted AS target_phone_encrypted + FROM contact_exchange_requests cer + JOIN users ru ON ru.id = cer.requester_id + JOIN users tu ON tu.id = cer.target_id + WHERE cer.deal_id = ? AND cer.accepted = TRUE`, + [dealId] + ); - res.json(rows); - } catch (error) { - console.error('Error in contacts deal route:', error); - res.status(500).json({ error: 'Internal server error' }); - } + res.json(rows); }); -export default router; \ No newline at end of file +export default router; diff --git a/backend/src/routes/helpRequests.js b/backend/src/routes/helpRequests.js index 981afa8..91a1b1a 100644 --- a/backend/src/routes/helpRequests.js +++ b/backend/src/routes/helpRequests.js @@ -6,41 +6,31 @@ import { requireAuth } from '../middleware/auth.js'; const router = Router(); router.get('/', async (_req, res) => { - try { - const [rows] = await pool.query( - `SELECT hr.id, hr.title, hr.description, hr.value_chf, hr.status, hr.created_at, u.display_name requester_name - FROM help_requests hr - JOIN users u ON u.id = hr.requester_id - ORDER BY hr.created_at DESC` - ); - res.json(rows); - } catch (error) { - console.error('Error fetching help requests:', error); - res.status(500).json({ error: 'Internal server error' }); - } + const [rows] = await pool.query( + `SELECT hr.id, hr.title, hr.description, hr.value_chf, hr.status, hr.created_at, u.display_name requester_name + FROM help_requests hr + JOIN users u ON u.id = hr.requester_id + ORDER BY hr.created_at DESC` + ); + res.json(rows); }); router.post('/', requireAuth, async (req, res) => { - try { - const parsed = z.object({ - title: z.string().min(3).max(180), - description: z.string().min(5), - valueChf: z.number().positive() - }).safeParse(req.body); + const parsed = z.object({ + title: z.string().min(3).max(180), + description: z.string().min(5), + valueChf: z.number().positive() + }).safeParse(req.body); - if (!parsed.success) return res.status(400).json({ error: parsed.error.flatten() }); + if (!parsed.success) return res.status(400).json({ error: parsed.error.flatten() }); - const { title, description, valueChf } = parsed.data; - const [result] = await pool.query( - 'INSERT INTO help_requests (requester_id, title, description, value_chf) VALUES (?, ?, ?, ?)', - [req.user.userId, title, description, valueChf] - ); + const { title, description, valueChf } = parsed.data; + const [result] = await pool.query( + 'INSERT INTO help_requests (requester_id, title, description, value_chf) VALUES (?, ?, ?, ?)', + [req.user.userId, title, description, valueChf] + ); - res.status(201).json({ id: result.insertId }); - } catch (error) { - console.error('Error creating help request:', error); - res.status(500).json({ error: 'Internal server error' }); - } + res.status(201).json({ id: result.insertId }); }); -export default router; \ No newline at end of file +export default router; diff --git a/backend/src/routes/offers.js b/backend/src/routes/offers.js index 1fd0ba0..676da1f 100644 --- a/backend/src/routes/offers.js +++ b/backend/src/routes/offers.js @@ -6,98 +6,59 @@ import { requireAuth } from '../middleware/auth.js'; const router = Router(); router.post('/:requestId', requireAuth, async (req, res) => { - try { - const requestId = Number(req.params.requestId); - if (Number.isNaN(requestId)) { - return res.status(400).json({ error: 'Invalid requestId' }); - } + const requestId = Number(req.params.requestId); + const parsed = z.object({ amountChf: z.number().positive(), message: z.string().max(2000).optional() }).safeParse(req.body); + if (!parsed.success || Number.isNaN(requestId)) return res.status(400).json({ error: 'Invalid payload' }); - const parsed = z.object({ - amountChf: z.number().positive(), - message: z.string().max(2000).optional() - }).safeParse(req.body); + const { amountChf, message } = parsed.data; + const [result] = await pool.query( + `INSERT INTO offers (request_id, helper_id, amount_chf, message) + VALUES (?, ?, ?, ?)`, + [requestId, req.user.userId, amountChf, message || null] + ); - if (!parsed.success) { - return res.status(400).json({ error: 'Invalid payload' }); - } + await pool.query('UPDATE help_requests SET status = ? WHERE id = ?', ['negotiating', requestId]); - const { amountChf, message } = parsed.data; - const [result] = await pool.query( - `INSERT INTO offers (request_id, helper_id, amount_chf, message) - VALUES (?, ?, ?, ?)`, - [requestId, req.user.userId, amountChf, message || null] - ); - - await pool.query('UPDATE help_requests SET status = ? WHERE id = ?', ['negotiating', requestId]); - - res.status(201).json({ id: result.insertId }); - } catch (error) { - console.error('Error in POST /offers/:requestId:', error); - res.status(500).json({ error: 'Internal server error' }); - } + res.status(201).json({ id: result.insertId }); }); router.post('/negotiation/:offerId', requireAuth, async (req, res) => { - try { - const offerId = Number(req.params.offerId); - if (Number.isNaN(offerId)) { - return res.status(400).json({ error: 'Invalid offerId' }); - } + const offerId = Number(req.params.offerId); + const parsed = z.object({ amountChf: z.number().positive(), message: z.string().max(2000).optional() }).safeParse(req.body); + if (!parsed.success || Number.isNaN(offerId)) return res.status(400).json({ error: 'Invalid payload' }); - const parsed = z.object({ - amountChf: z.number().positive(), - message: z.string().max(2000).optional() - }).safeParse(req.body); + const { amountChf, message } = parsed.data; + const [result] = await pool.query( + `INSERT INTO negotiations (offer_id, sender_id, amount_chf, message) + VALUES (?, ?, ?, ?)`, + [offerId, req.user.userId, amountChf, message || null] + ); - if (!parsed.success) { - return res.status(400).json({ error: 'Invalid payload' }); - } + await pool.query('UPDATE offers SET status = ? WHERE id = ?', ['countered', offerId]); - const { amountChf, message } = parsed.data; - const [result] = await pool.query( - `INSERT INTO negotiations (offer_id, sender_id, amount_chf, message) - VALUES (?, ?, ?, ?)`, - [offerId, req.user.userId, amountChf, message || null] - ); - - await pool.query('UPDATE offers SET status = ? WHERE id = ?', ['countered', offerId]); - - res.status(201).json({ id: result.insertId }); - } catch (error) { - console.error('Error in POST /offers/negotiation/:offerId:', error); - res.status(500).json({ error: 'Internal server error' }); - } + res.status(201).json({ id: result.insertId }); }); router.post('/accept/:offerId', requireAuth, async (req, res) => { - try { - const offerId = Number(req.params.offerId); - if (Number.isNaN(offerId)) { - return res.status(400).json({ error: 'Invalid offerId' }); - } + const offerId = Number(req.params.offerId); + if (Number.isNaN(offerId)) return res.status(400).json({ error: 'Invalid offerId' }); - const [offers] = await pool.query( - 'SELECT id, request_id, amount_chf FROM offers WHERE id = ? LIMIT 1', - [offerId] - ); - const offer = offers[0]; - if (!offer) { - return res.status(404).json({ error: 'Offer not found' }); - } + const [offers] = await pool.query( + 'SELECT id, request_id, amount_chf FROM offers WHERE id = ? LIMIT 1', + [offerId] + ); + const offer = offers[0]; + if (!offer) return res.status(404).json({ error: 'Offer not found' }); - await pool.query('UPDATE offers SET status = ? WHERE id = ?', ['accepted', offerId]); - await pool.query('UPDATE help_requests SET status = ? WHERE id = ?', ['agreed', offer.request_id]); + await pool.query('UPDATE offers SET status = ? WHERE id = ?', ['accepted', offerId]); + await pool.query('UPDATE help_requests SET status = ? WHERE id = ?', ['agreed', offer.request_id]); - const [dealResult] = await pool.query( - 'INSERT INTO deals (request_id, offer_id, agreed_amount_chf) VALUES (?, ?, ?)', - [offer.request_id, offer.id, offer.amount_chf] - ); + const [dealResult] = await pool.query( + 'INSERT INTO deals (request_id, offer_id, agreed_amount_chf) VALUES (?, ?, ?)', + [offer.request_id, offer.id, offer.amount_chf] + ); - res.status(201).json({ dealId: dealResult.insertId }); - } catch (error) { - console.error('Error in POST /offers/accept/:offerId:', error); - res.status(500).json({ error: 'Internal server error' }); - } + res.status(201).json({ dealId: dealResult.insertId }); }); -export default router; \ No newline at end of file +export default router; diff --git a/backend/src/routes/profile.js b/backend/src/routes/profile.js index 6ff1e7b..caa8dad 100644 --- a/backend/src/routes/profile.js +++ b/backend/src/routes/profile.js @@ -7,18 +7,13 @@ import { encryptText } from '../services/encryption.js'; const router = Router(); router.post('/phone', requireAuth, async (req, res) => { - try { - const parsed = z.object({ phone: z.string().min(6).max(40) }).safeParse(req.body); - if (!parsed.success) return res.status(400).json({ error: parsed.error.flatten() }); + const parsed = z.object({ phone: z.string().min(6).max(40) }).safeParse(req.body); + if (!parsed.success) return res.status(400).json({ error: parsed.error.flatten() }); - const encryptedPhone = encryptText(parsed.data.phone); - await pool.query('UPDATE users SET phone_encrypted = ? WHERE id = ?', [encryptedPhone, req.user.userId]); + const encryptedPhone = encryptText(parsed.data.phone); + await pool.query('UPDATE users SET phone_encrypted = ? WHERE id = ?', [encryptedPhone, req.user.userId]); - res.status(200).json({ status: 'updated' }); - } catch (error) { - console.error('Error updating phone:', error); - res.status(500).json({ error: 'Internal server error' }); - } + res.json({ status: 'updated' }); }); -export default router; \ No newline at end of file +export default router; diff --git a/backend/src/routes/reviews.js b/backend/src/routes/reviews.js index 3f0f2db..646e05a 100644 --- a/backend/src/routes/reviews.js +++ b/backend/src/routes/reviews.js @@ -6,35 +6,24 @@ import { requireAuth } from '../middleware/auth.js'; const router = Router(); router.post('/:dealId', requireAuth, async (req, res) => { - try { - const dealId = Number(req.params.dealId); - const parsed = 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 dealId = Number(req.params.dealId); + const parsed = z.object({ revieweeId: z.number().int().positive(), rating: z.number().int().min(1).max(5), comment: z.string().max(2000).optional() }).safeParse(req.body); - if (!parsed.success || Number.isNaN(dealId)) { - return res.status(400).json({ error: 'Invalid payload' }); - } + if (!parsed.success || Number.isNaN(dealId)) return res.status(400).json({ error: 'Invalid payload' }); - const now = new Date(); - const earliest = new Date(now.getTime() + 2 * 24 * 60 * 60 * 1000); - const latest = new Date(now.getTime() + 14 * 24 * 60 * 60 * 1000); + const now = new Date(); + const earliest = new Date(now.getTime() + 2 * 24 * 60 * 60 * 1000); + const latest = new Date(now.getTime() + 14 * 24 * 60 * 60 * 1000); - const { revieweeId, rating, comment } = parsed.data; + const { revieweeId, rating, comment } = parsed.data; - const [result] = await pool.query( - `INSERT INTO reviews (deal_id, reviewer_id, reviewee_id, rating, comment, earliest_prompt_at, latest_prompt_at) - VALUES (?, ?, ?, ?, ?, ?, ?)`, - [dealId, req.user.userId, revieweeId, rating, comment || null, earliest, latest] - ); + const [result] = await pool.query( + `INSERT INTO reviews (deal_id, reviewer_id, reviewee_id, rating, comment, earliest_prompt_at, latest_prompt_at) + VALUES (?, ?, ?, ?, ?, ?, ?)`, + [dealId, req.user.userId, revieweeId, rating, comment || null, earliest, latest] + ); - res.status(201).json({ id: result.insertId }); - } catch (error) { - console.error('Error creating review:', error); - res.status(500).json({ error: 'Internal server error' }); - } + res.status(201).json({ id: result.insertId }); }); -export default router; \ No newline at end of file +export default router;