UI data-driven sulle tabelle di config cfg_nis2_* (mig.046): - FrameworkController::catalog (GET /api/framework/catalog): 43 misure / 116 requisiti, procedura+rischio di default per requisito, flag importanti/essenziali, classe org. - public/misure-requisiti.html (Bootstrap Italia/AGID): vista per misura / per area politica, selettore soggetto (auto/importante/essenziale/tutti), righe che si 'spengono' per classe, ricerca, sola lettura (codifica non modificabile). Voce sidebar in sezione Compliance. - api.js frameworkCatalog(); routing index.php; i18n nav.framework IT/EN. - help.js: guida 'misure-requisiti' (struttura, importanti/essenziali, riferimenti art.23/24 D.Lgs.). - KB AI: doc SYSTEM ingestato (uuid 7871c1ea). - Cache-buster ?v=20260621 (35 pagine), version 1.18.0, SW cache nis2-shell-v1.18.0. - docs/simon/: file sorgente autoritativi (provenienza seed, codifica Simon non variata). Smoke prod: /framework/catalog 200 (43/116, 6 misure solo-essenziali, GV.OC-04->Proc.01/Risk.01), pagina 200, USR2 applicato. Additivo, nessuna modifica a dati esistenti. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
105 lines
4.4 KiB
PHP
105 lines
4.4 KiB
PHP
<?php
|
|
/**
|
|
* NIS2 Agile - Framework canonico Misure/Requisiti (Epic C / C1)
|
|
* ----------------------------------------------------------------------------
|
|
* Espone in SOLA LETTURA l'elenco canonico delle misure di sicurezza di base e
|
|
* dei relativi requisiti (Determinazione ACN n. 164179 del 14 aprile 2025),
|
|
* con la procedura e il rischio di default associati a ciascun requisito.
|
|
*
|
|
* Fonte dati: tabelle di CONFIGURAZIONE cfg_nis2_* (system-level), popolate dai
|
|
* file autoritativi forniti dal referente compliance (docs/simon/) — codifica
|
|
* NON variabile. Il dato NON e' org-scoped (e' framework normativo condiviso);
|
|
* l'unico contributo dell'org e' la sua CLASSE (essential/important), usata dal
|
|
* frontend per "spegnere" le righe non applicabili al soggetto.
|
|
*
|
|
* Sola lettura: nessun endpoint di scrittura. L'utente NON puo' modificare la
|
|
* codifica; la configurazione del framework e' riservata a super_admin/sistema
|
|
* (gestione futura). Vista doppia (per misura / per area politica a..p) gestita
|
|
* lato frontend sugli stessi dati.
|
|
*
|
|
* NOTE strutturali: DB API Database::query/fetchAll/fetchOne (NON Database::execute).
|
|
*/
|
|
|
|
require_once __DIR__ . '/BaseController.php';
|
|
|
|
class FrameworkController extends BaseController
|
|
{
|
|
/**
|
|
* GET /api/framework/catalog
|
|
* Ritorna ambiti NIST, misure (con requisiti annidati, procedura+rischio di
|
|
* default e flag di applicabilita' importanti/essenziali) e la classe dell'org
|
|
* corrente (se disponibile). Ordine 'ord'/'n' = ordine di default immutabile.
|
|
*/
|
|
public function catalog(): void
|
|
{
|
|
$this->requireAuth();
|
|
|
|
// Classe del soggetto (per evidenziare/spegnere le righe) — opzionale.
|
|
$orgClass = null;
|
|
$orgId = $this->getCurrentOrgId();
|
|
if ($orgId) {
|
|
$row = Database::fetchOne('SELECT entity_type FROM organizations WHERE id = ?', [$orgId]);
|
|
$orgClass = $row['entity_type'] ?? null; // essential | important | not_applicable
|
|
}
|
|
|
|
$ambiti = Database::fetchAll(
|
|
'SELECT nist_code, nist_descr FROM cfg_nis2_ambiti ORDER BY nist_code ASC'
|
|
);
|
|
|
|
$misure = Database::fetchAll(
|
|
'SELECT misura_code, nist_code, area_politica, misura_descr, ord,
|
|
applies_important, applies_essential
|
|
FROM cfg_nis2_misure
|
|
ORDER BY ord ASC'
|
|
);
|
|
|
|
$reqs = Database::fetchAll(
|
|
'SELECT q.n, q.misura_code, q.requisito_code, q.requisito_descr,
|
|
q.proc_code, p.proc_descr, q.risk_code, r.risk_descr,
|
|
q.applies_important, q.applies_essential
|
|
FROM cfg_nis2_requisiti q
|
|
LEFT JOIN cfg_nis2_procedure p ON p.proc_code = q.proc_code
|
|
LEFT JOIN cfg_nis2_rischi r ON r.risk_code = q.risk_code
|
|
ORDER BY q.n ASC, q.id ASC'
|
|
);
|
|
|
|
$byMis = [];
|
|
foreach ($reqs as $q) {
|
|
$byMis[$q['misura_code']][] = [
|
|
'n' => $q['n'] !== null ? (int) $q['n'] : null,
|
|
'requisito_code' => $q['requisito_code'],
|
|
'requisito_descr' => $q['requisito_descr'],
|
|
'proc_code' => $q['proc_code'],
|
|
'proc_descr' => $q['proc_descr'],
|
|
'risk_code' => $q['risk_code'],
|
|
'risk_descr' => $q['risk_descr'],
|
|
'applies_important' => (int) $q['applies_important'],
|
|
'applies_essential' => (int) $q['applies_essential'],
|
|
];
|
|
}
|
|
|
|
$measures = [];
|
|
foreach ($misure as $m) {
|
|
$measures[] = [
|
|
'misura_code' => $m['misura_code'],
|
|
'nist_code' => $m['nist_code'],
|
|
'area_politica' => $m['area_politica'],
|
|
'misura_descr' => $m['misura_descr'],
|
|
'ord' => (int) $m['ord'],
|
|
'applies_important' => (int) $m['applies_important'],
|
|
'applies_essential' => (int) $m['applies_essential'],
|
|
'requisiti' => $byMis[$m['misura_code']] ?? [],
|
|
];
|
|
}
|
|
|
|
$this->jsonSuccess([
|
|
'org_class' => $orgClass,
|
|
'ambiti' => $ambiti,
|
|
'measures' => $measures,
|
|
'totals' => ['misure' => count($measures), 'requisiti' => count($reqs)],
|
|
'readonly' => true,
|
|
'source' => 'Determinazione ACN n. 164179 del 14 aprile 2025',
|
|
]);
|
|
}
|
|
}
|