[FIX] simulate-nis2: seed DB diretto per evitare rate limit registrazione
- dbSeedUser(): inserisce utenti demo direttamente nel DB MySQL (bypass HTTP rate limit) - ensureUser(): usa dbSeedUser() come metodo primario, API /register come fallback - Rimosse le 2 chiamate register doppie (DEMO_EMAIL + email reale) - Aggiunto seed consultant@nis2agile.demo + membership a tutte le org demo Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d51c365e46
commit
eb31a0a504
@ -176,6 +176,39 @@ function apiOk(array $res, string $ctx = ''): bool
|
|||||||
|
|
||||||
// ── Idempotent helpers ───────────────────────────────────────────────────────
|
// ── Idempotent helpers ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seed utente direttamente nel DB (bypassa rate limit HTTP).
|
||||||
|
* Ritorna true se inserito/già esistente.
|
||||||
|
*/
|
||||||
|
function dbSeedUser(string $fullName, string $email, string $password, string $role): bool
|
||||||
|
{
|
||||||
|
$envFile = __DIR__ . '/.env';
|
||||||
|
if (!is_file($envFile)) return false;
|
||||||
|
$env = [];
|
||||||
|
foreach (file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
|
||||||
|
if (str_starts_with(trim($line), '#') || !str_contains($line, '=')) continue;
|
||||||
|
[$k, $v] = explode('=', $line, 2);
|
||||||
|
$env[trim($k)] = trim($v);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$dsn = sprintf('mysql:host=%s;port=%s;dbname=%s;charset=utf8mb4',
|
||||||
|
$env['DB_HOST'] ?? '127.0.0.1',
|
||||||
|
$env['DB_PORT'] ?? '3306',
|
||||||
|
$env['DB_NAME'] ?? 'nis2_agile_db'
|
||||||
|
);
|
||||||
|
$pdo = new PDO($dsn, $env['DB_USER'] ?? '', $env['DB_PASS'] ?? '', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
|
||||||
|
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 10]);
|
||||||
|
$pdo->prepare(
|
||||||
|
'INSERT INTO users (email, password_hash, full_name, role, is_active)
|
||||||
|
VALUES (?,?,?,?,1)
|
||||||
|
ON DUPLICATE KEY UPDATE password_hash=VALUES(password_hash), full_name=VALUES(full_name), role=VALUES(role), is_active=1'
|
||||||
|
)->execute([$email, $hash, $fullName, $role]);
|
||||||
|
return true;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Registra un utente se non esiste già, ritorna il JWT. */
|
/** Registra un utente se non esiste già, ritorna il JWT. */
|
||||||
function ensureUser(string $firstName, string $lastName, string $email, string $password, string $role = 'org_admin'): ?string
|
function ensureUser(string $firstName, string $lastName, string $email, string $password, string $role = 'org_admin'): ?string
|
||||||
{
|
{
|
||||||
@ -185,7 +218,7 @@ function ensureUser(string $firstName, string $lastName, string $email, string $
|
|||||||
return $S['users'][$email]['jwt'];
|
return $S['users'][$email]['jwt'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prova login
|
// Prova login prima (utente già esistente)
|
||||||
$loginRes = api('POST', '/auth/login', ['email' => $email, 'password' => $password]);
|
$loginRes = api('POST', '/auth/login', ['email' => $email, 'password' => $password]);
|
||||||
if (!empty($loginRes['data']['access_token'])) {
|
if (!empty($loginRes['data']['access_token'])) {
|
||||||
$jwt = $loginRes['data']['access_token'];
|
$jwt = $loginRes['data']['access_token'];
|
||||||
@ -194,39 +227,33 @@ function ensureUser(string $firstName, string $lastName, string $email, string $
|
|||||||
return $jwt;
|
return $jwt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registrazione
|
// Seed diretto nel DB (evita rate limit HTTP su /auth/register)
|
||||||
$regRes = api('POST', '/auth/register', [
|
$fullName = trim("$firstName $lastName");
|
||||||
'full_name' => trim("$firstName $lastName"),
|
if (dbSeedUser($fullName, $email, $password, $role)) {
|
||||||
'email' => DEMO_EMAIL !== $email ? DEMO_EMAIL : $email,
|
|
||||||
'password' => $password,
|
|
||||||
'role' => $role,
|
|
||||||
]);
|
|
||||||
// Override email per demo (sempre DEMO_EMAIL ma tracking per slug)
|
|
||||||
$regRes2 = api('POST', '/auth/register', [
|
|
||||||
'full_name' => trim("$firstName $lastName"),
|
|
||||||
'email' => $email,
|
|
||||||
'password' => $password,
|
|
||||||
'role' => $role,
|
|
||||||
]);
|
|
||||||
if (!empty($regRes2['data']['access_token'])) {
|
|
||||||
$jwt = $regRes2['data']['access_token'];
|
|
||||||
$uid = $regRes2['data']['user']['id'] ?? null;
|
|
||||||
$S['users'][$email] = ['jwt' => $jwt, 'id' => $uid];
|
|
||||||
ok("Registrato: $firstName $lastName <$email>");
|
|
||||||
return $jwt;
|
|
||||||
}
|
|
||||||
if (!empty($regRes2['success'])) {
|
|
||||||
// Login dopo registrazione
|
|
||||||
$loginRes2 = api('POST', '/auth/login', ['email' => $email, 'password' => $password]);
|
$loginRes2 = api('POST', '/auth/login', ['email' => $email, 'password' => $password]);
|
||||||
if (!empty($loginRes2['data']['access_token'])) {
|
if (!empty($loginRes2['data']['access_token'])) {
|
||||||
$jwt = $loginRes2['data']['access_token'];
|
$jwt = $loginRes2['data']['access_token'];
|
||||||
$S['users'][$email] = ['jwt' => $jwt, 'id' => $loginRes2['data']['user']['id'] ?? null];
|
$S['users'][$email] = ['jwt' => $jwt, 'id' => $loginRes2['data']['user']['id'] ?? null];
|
||||||
ok("Registrato + login: $firstName $lastName <$email>");
|
ok("Registrato: $firstName $lastName <$email>");
|
||||||
return $jwt;
|
return $jwt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fail("Registrazione fallita per $email: " . ($regRes2['error'] ?? 'errore'));
|
// Fallback: registrazione via API
|
||||||
|
$regRes = api('POST', '/auth/register', [
|
||||||
|
'full_name' => $fullName,
|
||||||
|
'email' => $email,
|
||||||
|
'password' => $password,
|
||||||
|
'role' => $role,
|
||||||
|
]);
|
||||||
|
if (!empty($regRes['data']['access_token'])) {
|
||||||
|
$jwt = $regRes['data']['access_token'];
|
||||||
|
$S['users'][$email] = ['jwt' => $jwt, 'id' => $regRes['data']['user']['id'] ?? null];
|
||||||
|
ok("Registrato (API): $firstName $lastName <$email>");
|
||||||
|
return $jwt;
|
||||||
|
}
|
||||||
|
|
||||||
|
fail("Registrazione fallita per $email: " . ($regRes['message'] ?? 'errore'));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,6 +674,34 @@ foreach ($COMPANIES as $slug => $comp) {
|
|||||||
info(" {$comp['name']}: {$comp['employees']} dip, fatturato " . number_format($comp['annual_turnover']/1000000, 1) . "M€, settore {$comp['sector']}");
|
info(" {$comp['name']}: {$comp['employees']} dip, fatturato " . number_format($comp['annual_turnover']/1000000, 1) . "M€, settore {$comp['sector']}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Seed consulente demo (cross-org, accesso a tutte le aziende) ─────────────
|
||||||
|
$consultantEmail = 'consultant@nis2agile.demo';
|
||||||
|
$consultantJwt = ensureUser('Marco', 'Consulente', $consultantEmail, DEMO_PWD, 'consultant');
|
||||||
|
if ($consultantJwt) {
|
||||||
|
// Aggiungi il consultant a tutte le org create
|
||||||
|
foreach ($S['orgs'] as $slug => $orgData) {
|
||||||
|
if (empty($orgData['id'])) continue;
|
||||||
|
$orgId = $orgData['id'];
|
||||||
|
// Verifica se già membro
|
||||||
|
$envFile = __DIR__ . '/.env';
|
||||||
|
$env = [];
|
||||||
|
foreach (file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
|
||||||
|
if (!str_contains($line, '=')) continue;
|
||||||
|
[$k, $v] = explode('=', $line, 2);
|
||||||
|
$env[trim($k)] = trim($v);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$dsn = sprintf('mysql:host=%s;port=%s;dbname=%s;charset=utf8mb4', $env['DB_HOST']??'127.0.0.1', $env['DB_PORT']??'3306', $env['DB_NAME']??'nis2_agile_db');
|
||||||
|
$pdo = new PDO($dsn, $env['DB_USER']??'', $env['DB_PASS']??'', [PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION]);
|
||||||
|
$uid = $S['users'][$consultantEmail]['id'] ?? null;
|
||||||
|
if ($uid) {
|
||||||
|
$pdo->prepare('INSERT IGNORE INTO user_organizations (user_id, organization_id, role) VALUES (?,?,\'consultant\')')->execute([$uid, $orgId]);
|
||||||
|
ok("Consultant aggiunto a org #{$orgId} ({$orgData['name']})");
|
||||||
|
}
|
||||||
|
} catch (\Throwable) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ────────────────────────────────────────────────────────────────────────────
|
// ────────────────────────────────────────────────────────────────────────────
|
||||||
// SIM-01 — FASE 3: Gap Assessment 80 domande per ogni azienda
|
// SIM-01 — FASE 3: Gap Assessment 80 domande per ogni azienda
|
||||||
// ────────────────────────────────────────────────────────────────────────────
|
// ────────────────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user