Files
InsanityLab-web/src/lib/contact.ts
T
Adriano b17b5c831a Fix contatti + rinomina servizi + orario sabato
- Contatti: rate-limit per IP reale (X-Forwarded-For) invece dell'IP del
  proxy Traefik, condiviso da tutti; controllo spostato dopo la validazione
  così bot/honeypot non consumano la quota. Honeypot rinominato da "website"
  a "hp_field" per non farlo riempire dall'autofill del browser (falsi 400).
- Servizi: "Performance Class" -> "Class" (titolo/card/H1/footer); migrazione
  DB invertita e guardata.
- One to One: migrazione titolo prod "Personal training" -> "One to One".
- Footer: orario sabato 8-17 (non 8-19), seed + migrazione guardata.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 17:58:26 +02:00

35 lines
1.5 KiB
TypeScript

export interface ContactData {
firstName: string; lastName: string; phone: string;
email: string; message: string; hpField: string;
}
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
function str(v: unknown, max: number): string {
return typeof v === 'string' ? v.trim().slice(0, max + 1) : '';
}
export function validateContact(data: unknown):
| { ok: true; value: ContactData }
| { ok: false; error: string } {
if (typeof data !== 'object' || data === null) return { ok: false, error: 'Dati non validi.' };
const d = data as Record<string, unknown>;
const value: ContactData = {
firstName: str(d.firstName, 100),
lastName: str(d.lastName, 100),
phone: str(d.phone, 40),
email: str(d.email, 200),
message: str(d.message, 5000),
// Honeypot: nome neutro per non farlo riempire dall'autofill del browser.
hpField: str(d.hp_field, 200),
};
if (value.hpField) return { ok: false, error: 'Richiesta non valida.' };
if (!value.firstName) return { ok: false, error: 'Il nome è obbligatorio.' };
if (!value.lastName) return { ok: false, error: 'Il cognome è obbligatorio.' };
if (!value.phone) return { ok: false, error: 'Il telefono è obbligatorio.' };
if (!EMAIL_RE.test(value.email)) return { ok: false, error: 'Inserisci una e-mail valida.' };
if (!value.message) return { ok: false, error: 'Il messaggio è obbligatorio.' };
if (value.message.length > 5000) return { ok: false, error: 'Messaggio troppo lungo.' };
return { ok: true, value };
}