import { Router } from 'express'; import { createHash, randomInt } from 'crypto'; import { z } from 'zod'; import { pool } from '../db/connection.js'; import { requireAuth } from '../middleware/auth.js'; const router = Router(); const hashCode = (code) => createHash('sha256').update(code).digest('hex'); router.post('/change-request', requireAuth, async (req, res) => { const parsed = z.object({ newAddressEncrypted: z.string().min(10) }).safeParse(req.body); if (!parsed.success) return res.status(400).json({ error: parsed.error.flatten() }); const verificationCode = String(randomInt(100000, 999999)); const verificationCodeHash = hashCode(verificationCode); const [result] = await pool.query( `INSERT INTO address_change_requests (user_id, new_address_encrypted, verification_code_hash) VALUES (?, ?, ?)`, [req.user.userId, parsed.data.newAddressEncrypted, verificationCodeHash] ); 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) => { 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 [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' }); 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;