Files
nav-carte/server/api/report.post.ts
2026-04-28 14:00:05 +02:00

95 lines
3.1 KiB
TypeScript

/**
* POST /api/report
*
* Signalement d'erreur / proposition de modification sur une fiche
* Fallback Resend (pas de table NocoDB créée)
*
* Body : { fiche_id: number, message: string, email: string }
* Rate limit : 5/IP/jour
* Envoi vers jules@trans-former.fr via Resend API
*/
import { checkRateLimitJson } from '~/server/utils/rateLimitJson'
const EMAIL_JULES = process.env.EMAIL_JULES || 'jules@trans-former.fr'
export default defineEventHandler(async (event) => {
// 1. IP
const ip =
getHeader(event, 'x-forwarded-for')?.split(',')[0].trim() ||
event.node.req.socket?.remoteAddress ||
'0.0.0.0'
// 2. Rate limit 5/IP/jour
const allowed = checkRateLimitJson(ip, 'report', 5)
if (!allowed) {
throw createError({
statusCode: 429,
statusMessage: 'Limite de 5 signalements par jour atteinte.',
})
}
// 3. Lire le body
const body = await readBody(event)
const fiche_id: number = Number(body?.fiche_id ?? 0)
const message: string = (body?.message ?? '').trim()
const email: string = (body?.email ?? '').trim()
// 4. Validation
if (!fiche_id || fiche_id <= 0) {
throw createError({ statusCode: 400, statusMessage: 'fiche_id invalide.' })
}
if (!message || message.length < 5 || message.length > 500) {
throw createError({ statusCode: 400, statusMessage: 'Message requis (5-500 caractères).' })
}
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
if (!email || !emailRegex.test(email)) {
throw createError({ statusCode: 400, statusMessage: 'Email invalide.' })
}
// 5. Envoi via Resend
const resendApiKey = process.env.RESEND_API_KEY
if (!resendApiKey) {
console.error('[report] RESEND_API_KEY manquante')
throw createError({ statusCode: 500, statusMessage: 'Configuration email manquante.' })
}
const submittedAt = new Date().toLocaleString('fr-FR', { timeZone: 'Europe/Paris' })
try {
await $fetch('https://api.resend.com/emails', {
method: 'POST',
headers: {
Authorization: `Bearer ${resendApiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
from: 'AEP Signalement <noreply@trans-former.fr>',
to: EMAIL_JULES,
subject: `[AEP] Signalement fiche #${fiche_id}`,
html: `
<h2>Signalement fiche AEP #${fiche_id}</h2>
<p><strong>Date :</strong> ${submittedAt}</p>
<p><strong>Email expéditeur :</strong> ${email}</p>
<p><strong>Message :</strong></p>
<blockquote style="border-left:3px solid #ccc;padding-left:12px;color:#555;">
${message.replace(/\n/g, '<br/>')}
</blockquote>
<hr/>
<p style="font-size:12px;color:#999;">
Voir la fiche : <a href="https://aep.trans-former.fr/fiche/${fiche_id}">https://aep.trans-former.fr/fiche/${fiche_id}</a>
</p>
`,
}),
})
} catch (e: any) {
console.error('[report] Erreur Resend:', e?.message ?? e)
throw createError({
statusCode: 502,
statusMessage: 'Erreur envoi email — réessaie dans quelques instants.',
})
}
return { ok: true, message: 'Signalement envoyé, merci !' }
})