nis2-agile/application/controllers/ContactController.php
DevEnv nis2-agile b909136d53 [FIX] MktgLeadController + ContactController: rimuovi parent::__construct()
BaseController non ha costruttore — la chiamata parent::__construct()
causava Fatal Error "Cannot call constructor" su ogni richiesta.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 12:18:14 +01:00

147 lines
6.7 KiB
PHP

<?php
/**
* ContactController — Gestione lead e richieste codice invito
*
* Endpoint pubblici (no auth):
* POST /api/contact/request-invite → richiesta accesso con codice invito
*/
require_once APP_PATH . '/controllers/BaseController.php';
require_once APP_PATH . '/services/EmailService.php';
class ContactController extends BaseController
{
private EmailService $email;
public function __construct()
{
$this->email = new EmailService();
}
/**
* POST /api/contact/request-invite
* Raccoglie i dati del lead e invia notifica a info@agile.software
*/
public function requestInvite(): void
{
// Rate limit: max 3 richieste / 10 min per IP
$ip = $this->getClientIP();
$key = 'contact_' . md5($ip);
$cacheFile = sys_get_temp_dir() . '/nis2_contact_' . $key;
$now = time();
if (file_exists($cacheFile)) {
$data = json_decode(file_get_contents($cacheFile), true);
$data['requests'] = array_filter($data['requests'] ?? [], fn($t) => $t > ($now - 600));
if (count($data['requests']) >= 3) {
$this->jsonError('Troppe richieste. Riprova tra qualche minuto.', 429);
return;
}
} else {
$data = ['requests' => []];
}
$data['requests'][] = $now;
file_put_contents($cacheFile, json_encode($data));
// Validazione input
$body = $this->getRequestBody();
$nome = trim($body['nome'] ?? '');
$email = trim($body['email'] ?? '');
$azienda = trim($body['azienda'] ?? '');
$ruolo = trim($body['ruolo'] ?? '');
$dimensioni = trim($body['dimensioni'] ?? '');
$messaggio = trim($body['messaggio'] ?? '');
if (!$nome || !$email || !$azienda || !$ruolo) {
$this->jsonError('Compila tutti i campi obbligatori (nome, email, azienda, ruolo).', 422);
return;
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$this->jsonError('Indirizzo email non valido.', 422);
return;
}
// Sanitize
$nome = htmlspecialchars($nome, ENT_QUOTES, 'UTF-8');
$email = htmlspecialchars($email, ENT_QUOTES, 'UTF-8');
$azienda = htmlspecialchars($azienda, ENT_QUOTES, 'UTF-8');
$ruolo = htmlspecialchars($ruolo, ENT_QUOTES, 'UTF-8');
$dimensioni = htmlspecialchars($dimensioni, ENT_QUOTES, 'UTF-8');
$messaggio = htmlspecialchars($messaggio, ENT_QUOTES, 'UTF-8');
$date = date('d/m/Y H:i');
$html = "
<div style='font-family:Inter,Arial,sans-serif;max-width:600px;margin:0 auto;'>
<div style='background:#0F172A;padding:24px 32px;border-radius:12px 12px 0 0;'>
<h2 style='color:#06B6D4;margin:0;font-size:20px;'>
🛡️ Nuova richiesta codice invito — NIS2 Agile
</h2>
<p style='color:#94A3B8;margin:6px 0 0;font-size:13px;'>Ricevuta il {$date}</p>
</div>
<div style='background:#1E293B;padding:28px 32px;border-radius:0 0 12px 12px;'>
<table style='width:100%;border-collapse:collapse;'>
<tr>
<td style='padding:10px 0;color:#94A3B8;font-size:13px;width:140px;vertical-align:top;'>Nome</td>
<td style='padding:10px 0;color:#F8FAFC;font-size:14px;font-weight:600;'>{$nome}</td>
</tr>
<tr style='border-top:1px solid rgba(6,182,212,0.1);'>
<td style='padding:10px 0;color:#94A3B8;font-size:13px;vertical-align:top;'>Email</td>
<td style='padding:10px 0;color:#06B6D4;font-size:14px;'><a href='mailto:{$email}' style='color:#06B6D4;'>{$email}</a></td>
</tr>
<tr style='border-top:1px solid rgba(6,182,212,0.1);'>
<td style='padding:10px 0;color:#94A3B8;font-size:13px;vertical-align:top;'>Azienda/Studio</td>
<td style='padding:10px 0;color:#F8FAFC;font-size:14px;font-weight:600;'>{$azienda}</td>
</tr>
<tr style='border-top:1px solid rgba(6,182,212,0.1);'>
<td style='padding:10px 0;color:#94A3B8;font-size:13px;vertical-align:top;'>Ruolo</td>
<td style='padding:10px 0;color:#F8FAFC;font-size:14px;'>{$ruolo}</td>
</tr>
" . ($dimensioni ? "
<tr style='border-top:1px solid rgba(6,182,212,0.1);'>
<td style='padding:10px 0;color:#94A3B8;font-size:13px;vertical-align:top;'>Dimensioni</td>
<td style='padding:10px 0;color:#F8FAFC;font-size:14px;'>{$dimensioni}</td>
</tr>" : "") . "
" . ($messaggio ? "
<tr style='border-top:1px solid rgba(6,182,212,0.1);'>
<td style='padding:10px 0;color:#94A3B8;font-size:13px;vertical-align:top;'>Messaggio</td>
<td style='padding:10px 0;color:#F8FAFC;font-size:14px;line-height:1.6;'>{$messaggio}</td>
</tr>" : "") . "
<tr style='border-top:1px solid rgba(6,182,212,0.1);'>
<td style='padding:10px 0;color:#94A3B8;font-size:13px;vertical-align:top;'>IP</td>
<td style='padding:10px 0;color:#64748B;font-size:12px;'>{$ip}</td>
</tr>
</table>
<div style='margin-top:24px;padding:16px;background:rgba(6,182,212,0.06);border-radius:8px;border:1px solid rgba(6,182,212,0.15);'>
<p style='margin:0;color:#94A3B8;font-size:13px;'>
Rispondi a questo lead generando un codice invito da:
<a href='https://nis2.agile.software/licenseExt.html' style='color:#06B6D4;'>licenseExt.html</a>
</p>
</div>
</div>
</div>";
$sent = $this->email->send(
'info@agile.software',
"🛡️ Richiesta accesso NIS2 Agile — {$nome} ({$azienda})",
$html,
'noreply@agile.software'
);
if (!$sent) {
$this->jsonError('Errore nell\'invio della richiesta. Prova a contattarci direttamente a info@agile.software.', 500);
return;
}
$this->jsonSuccess(null, 'Richiesta inviata! Ti contatteremo entro 24 ore con il tuo codice di accesso.');
}
private function getClientIP(): string
{
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
return trim($ips[0]);
}
return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}
}