[BACKEND] Completa backend: validate-invite, lookup-piva, ruoli, SIM-06

AuthController:
- register() accetta `role` diretto (compliance_manager, org_admin, auditor, board_member, consultant)
- Aggiunto validateInvite() → POST /api/auth/validate-invite (no auth)

OnboardingController:
- Aggiunto lookupPiva() → POST /api/onboarding/lookup-piva (no auth, rate limit 10/min)
  usato da register.html per P.IVA lookup pre-login

Router (index.php):
- Aggiunto POST:validateInvite e POST:lookupPiva

api.js:
- register() invia sia `role` che `user_type` per retrocompatibilità

simulate-nis2.php:
- SIM-06: B2B provisioning via X-Provision-Secret → org + JWT + API Key
- Filtro NIS2_SIM=SIM06 via goto per skip SIM-01→05 indipendenti
- readEnvValue() helper per leggere PROVISION_SECRET da .env

register.html:
- lookupPiva usa /onboarding/lookup-piva (endpoint pubblico)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
DevEnv nis2-agile
2026-03-07 17:23:16 +01:00
co-authored by Claude Sonnet 4.6
parent e4e7d94043
commit ab0e3755f4
6 changed files with 282 additions and 10 deletions
+53 -2
View File
@@ -45,8 +45,19 @@ class AuthController extends BaseController
$password = $this->getParam('password');
$fullName = trim($this->getParam('full_name'));
$phone = $this->getParam('phone');
$userType = $this->getParam('user_type', 'azienda'); // 'azienda' | 'consultant'
$role = ($userType === 'consultant') ? 'consultant' : 'employee';
// Supporta sia `role` diretto (nuovo register.html) che `user_type` legacy
$validRoles = ['super_admin', 'org_admin', 'compliance_manager', 'board_member', 'auditor', 'employee', 'consultant'];
$roleParam = trim($this->getParam('role', ''));
$userType = $this->getParam('user_type', 'azienda');
if ($roleParam && in_array($roleParam, $validRoles, true) && $roleParam !== 'super_admin') {
$role = $roleParam;
} elseif ($userType === 'consultant') {
$role = 'consultant';
} else {
$role = 'employee';
}
// Validazione email
if (!$this->validateEmail($email)) {
@@ -319,4 +330,44 @@ class AuthController extends BaseController
$this->jsonSuccess(null, 'Password modificata. Effettua nuovamente il login.');
}
/**
* POST /api/auth/validate-invite
*
* Valida un codice invito B2B e restituisce piano e metadati.
* Nessuna autenticazione richiesta — usato dalla pagina register.html
* prima della registrazione per mostrare l'anteprima del piano.
*
* Body: { "invite_token": "inv_xxxx..." }
* Response: { valid: true, plan: "professional", duration_months: 12, ... }
*/
public function validateInvite(): void
{
$token = trim($this->getParam('invite_token', ''));
if (!$token) {
$this->jsonError('invite_token mancante', 400, 'MISSING_TOKEN');
}
require_once APP_PATH . '/controllers/InviteController.php';
$result = InviteController::resolveInvite($token);
if (!$result['valid']) {
$this->jsonError($result['error'], 422, $result['code'] ?? 'INVALID_INVITE');
}
$inv = $result['invite'];
$this->jsonSuccess([
'valid' => true,
'plan' => $inv['plan'],
'duration_months' => (int) $inv['duration_months'],
'expires_at' => $inv['expires_at'],
'remaining_uses' => (int)$inv['max_uses'] - (int)$inv['used_count'],
'channel' => $inv['channel'],
'label' => $inv['label'],
'restrict_vat' => $inv['restrict_vat'] ? true : false,
'restrict_email' => $inv['restrict_email'] ? true : false,
], 'Invito valido');
}
}