feat(privat/CV): sync to latest upstream (cv-upstream/main, 30f9608b)
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Anti-spam middleware for public forms.
|
||||
*
|
||||
* Two complementary checks:
|
||||
* 1. Honeypot — a hidden field (`company_website`) that real users never see.
|
||||
* If it is filled, the request is a bot. We respond with a fake success
|
||||
* so the bot does not learn it was detected.
|
||||
* 2. Time trap — a `form_started_at` timestamp set by the client when the form
|
||||
* is rendered. Submissions faster than MIN_FILL_MS are almost certainly bots.
|
||||
*
|
||||
* Both fields are stripped from req.body before reaching route handlers.
|
||||
*/
|
||||
const MIN_FILL_MS = 2000 // 2 seconds
|
||||
|
||||
export function antiSpam(req, res, next) {
|
||||
const { company_website, form_started_at } = req.body || {}
|
||||
|
||||
// Honeypot filled → silently pretend success
|
||||
if (company_website) {
|
||||
return res.status(201).json({ ok: true, message: 'Bestätigungs-E-Mail gesendet.' })
|
||||
}
|
||||
|
||||
// Time trap → too fast to be human
|
||||
if (form_started_at) {
|
||||
const elapsed = Date.now() - Number(form_started_at)
|
||||
if (Number.isFinite(elapsed) && elapsed >= 0 && elapsed < MIN_FILL_MS) {
|
||||
return res.status(201).json({ ok: true, message: 'Bestätigungs-E-Mail gesendet.' })
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up internal fields before route handlers use req.body
|
||||
if (req.body) {
|
||||
delete req.body.company_website
|
||||
delete req.body.form_started_at
|
||||
}
|
||||
|
||||
next()
|
||||
}
|
||||
Reference in New Issue
Block a user