[FIX] ServicesController: allineamento colonne DB reali (risk_level, contained_at, owner_name, company_name, category compliance_controls)
This commit is contained in:
parent
27ec63c28d
commit
159d783ed7
@ -855,13 +855,13 @@ class ServicesController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Risk summary
|
// Risk summary (risk_level calcolato da inherent_risk_score: >=16 critical, >=9 high)
|
||||||
$riskStats = Database::fetchOne(
|
$riskStats = Database::fetchOne(
|
||||||
'SELECT
|
'SELECT
|
||||||
COUNT(*) as total,
|
COUNT(*) as total,
|
||||||
SUM(CASE WHEN status = "open" THEN 1 ELSE 0 END) as open_count,
|
SUM(CASE WHEN status NOT IN ("closed") THEN 1 ELSE 0 END) as open_count,
|
||||||
SUM(CASE WHEN risk_level IN ("high","critical") AND status = "open" THEN 1 ELSE 0 END) as high_critical,
|
SUM(CASE WHEN inherent_risk_score >= 9 AND status NOT IN ("closed") THEN 1 ELSE 0 END) as high_critical,
|
||||||
SUM(CASE WHEN status = "mitigated" THEN 1 ELSE 0 END) as mitigated
|
SUM(CASE WHEN status = "monitored" THEN 1 ELSE 0 END) as mitigated
|
||||||
FROM risks WHERE organization_id = ?',
|
FROM risks WHERE organization_id = ?',
|
||||||
[$orgId]
|
[$orgId]
|
||||||
);
|
);
|
||||||
@ -870,9 +870,9 @@ class ServicesController extends BaseController
|
|||||||
$incidentStats = Database::fetchOne(
|
$incidentStats = Database::fetchOne(
|
||||||
'SELECT
|
'SELECT
|
||||||
COUNT(*) as total,
|
COUNT(*) as total,
|
||||||
SUM(CASE WHEN status = "open" OR status = "investigating" THEN 1 ELSE 0 END) as open_count,
|
SUM(CASE WHEN status NOT IN ("closed","post_mortem") THEN 1 ELSE 0 END) as open_count,
|
||||||
SUM(CASE WHEN is_significant = 1 THEN 1 ELSE 0 END) as significant,
|
SUM(CASE WHEN is_significant = 1 THEN 1 ELSE 0 END) as significant,
|
||||||
SUM(CASE WHEN early_warning_sent = 1 THEN 1 ELSE 0 END) as notified_acn
|
SUM(CASE WHEN early_warning_sent_at IS NOT NULL THEN 1 ELSE 0 END) as notified_acn
|
||||||
FROM incidents WHERE organization_id = ?',
|
FROM incidents WHERE organization_id = ?',
|
||||||
[$orgId]
|
[$orgId]
|
||||||
);
|
);
|
||||||
@ -944,10 +944,18 @@ class ServicesController extends BaseController
|
|||||||
$params = [$orgId];
|
$params = [$orgId];
|
||||||
|
|
||||||
if (!empty($_GET['level'])) {
|
if (!empty($_GET['level'])) {
|
||||||
|
// risk_level è calcolato da inherent_risk_score
|
||||||
|
$levelMap = ['critical' => 16, 'high' => 9, 'medium' => 4, 'low' => 0];
|
||||||
$levels = array_filter(explode(',', $_GET['level']));
|
$levels = array_filter(explode(',', $_GET['level']));
|
||||||
$placeholders = implode(',', array_fill(0, count($levels), '?'));
|
$conditions = [];
|
||||||
$where .= " AND r.risk_level IN ({$placeholders})";
|
foreach ($levels as $lv) {
|
||||||
$params = array_merge($params, $levels);
|
$lv = strtolower(trim($lv));
|
||||||
|
if ($lv === 'critical') { $conditions[] = 'r.inherent_risk_score >= 16'; }
|
||||||
|
elseif ($lv === 'high') { $conditions[] = '(r.inherent_risk_score >= 9 AND r.inherent_risk_score < 16)'; }
|
||||||
|
elseif ($lv === 'medium') { $conditions[] = '(r.inherent_risk_score >= 4 AND r.inherent_risk_score < 9)'; }
|
||||||
|
elseif ($lv === 'low') { $conditions[] = 'r.inherent_risk_score < 4'; }
|
||||||
|
}
|
||||||
|
if ($conditions) $where .= ' AND ('.implode(' OR ', $conditions).')';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($_GET['area'])) {
|
if (!empty($_GET['area'])) {
|
||||||
@ -969,8 +977,12 @@ class ServicesController extends BaseController
|
|||||||
|
|
||||||
$risks = Database::fetchAll(
|
$risks = Database::fetchAll(
|
||||||
"SELECT r.id, r.title, r.description, r.category, r.likelihood,
|
"SELECT r.id, r.title, r.description, r.category, r.likelihood,
|
||||||
r.impact, r.inherent_risk_score, r.risk_level, r.status,
|
r.impact, r.inherent_risk_score,
|
||||||
r.treatment_plan, r.owner_name, r.residual_risk_score,
|
CASE WHEN r.inherent_risk_score >= 16 THEN 'critical'
|
||||||
|
WHEN r.inherent_risk_score >= 9 THEN 'high'
|
||||||
|
WHEN r.inherent_risk_score >= 4 THEN 'medium'
|
||||||
|
ELSE 'low' END as risk_level,
|
||||||
|
r.status, r.treatment, r.residual_risk_score,
|
||||||
r.created_at, r.updated_at
|
r.created_at, r.updated_at
|
||||||
FROM risks r
|
FROM risks r
|
||||||
WHERE {$where}
|
WHERE {$where}
|
||||||
@ -1035,12 +1047,10 @@ class ServicesController extends BaseController
|
|||||||
|
|
||||||
$incidents = Database::fetchAll(
|
$incidents = Database::fetchAll(
|
||||||
"SELECT id, title, classification, severity, status, is_significant,
|
"SELECT id, title, classification, severity, status, is_significant,
|
||||||
detected_at, contained_at, resolved_at,
|
detected_at, closed_at,
|
||||||
early_warning_sent, early_warning_sent_at,
|
early_warning_sent_at, notification_sent_at, final_report_sent_at,
|
||||||
notification_sent, notification_sent_at,
|
early_warning_due, notification_due, final_report_due,
|
||||||
final_report_sent, final_report_sent_at,
|
affected_services, root_cause,
|
||||||
notification_deadline, final_report_deadline,
|
|
||||||
affected_systems, impact_description,
|
|
||||||
created_at, updated_at
|
created_at, updated_at
|
||||||
FROM incidents
|
FROM incidents
|
||||||
WHERE {$where}
|
WHERE {$where}
|
||||||
@ -1057,20 +1067,20 @@ class ServicesController extends BaseController
|
|||||||
'early_warning_24h' => [
|
'early_warning_24h' => [
|
||||||
'required' => (bool)$inc['is_significant'],
|
'required' => (bool)$inc['is_significant'],
|
||||||
'deadline' => date('c', $detectedTs + 86400),
|
'deadline' => date('c', $detectedTs + 86400),
|
||||||
'sent' => (bool)$inc['early_warning_sent'],
|
'sent' => $inc['early_warning_sent_at'] !== null,
|
||||||
'overdue' => !$inc['early_warning_sent'] && $now > $detectedTs + 86400,
|
'overdue' => !$inc['early_warning_sent_at'] && $now > $detectedTs + 86400,
|
||||||
],
|
],
|
||||||
'notification_72h' => [
|
'notification_72h' => [
|
||||||
'required' => (bool)$inc['is_significant'],
|
'required' => (bool)$inc['is_significant'],
|
||||||
'deadline' => date('c', $detectedTs + 259200),
|
'deadline' => date('c', $detectedTs + 259200),
|
||||||
'sent' => (bool)$inc['notification_sent'],
|
'sent' => $inc['notification_sent_at'] !== null,
|
||||||
'overdue' => !$inc['notification_sent'] && $now > $detectedTs + 259200,
|
'overdue' => !$inc['notification_sent_at'] && $now > $detectedTs + 259200,
|
||||||
],
|
],
|
||||||
'final_report_30d' => [
|
'final_report_30d' => [
|
||||||
'required' => (bool)$inc['is_significant'],
|
'required' => (bool)$inc['is_significant'],
|
||||||
'deadline' => date('c', $detectedTs + 2592000),
|
'deadline' => date('c', $detectedTs + 2592000),
|
||||||
'sent' => (bool)$inc['final_report_sent'],
|
'sent' => $inc['final_report_sent_at'] !== null,
|
||||||
'overdue' => !$inc['final_report_sent'] && $now > $detectedTs + 2592000,
|
'overdue' => !$inc['final_report_sent_at'] && $now > $detectedTs + 2592000,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -1099,28 +1109,28 @@ class ServicesController extends BaseController
|
|||||||
$orgId = $this->currentOrgId;
|
$orgId = $this->currentOrgId;
|
||||||
|
|
||||||
$controls = Database::fetchAll(
|
$controls = Database::fetchAll(
|
||||||
'SELECT id, control_code, title, category, status,
|
'SELECT id, control_code, title, framework, status,
|
||||||
implementation_notes, due_date, updated_at
|
implementation_percentage, evidence_description, next_review_date, updated_at
|
||||||
FROM compliance_controls
|
FROM compliance_controls
|
||||||
WHERE organization_id = ?
|
WHERE organization_id = ?
|
||||||
ORDER BY category, control_code',
|
ORDER BY framework, control_code',
|
||||||
[$orgId]
|
[$orgId]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Raggruppa per categoria
|
// Raggruppa per framework
|
||||||
$byCategory = [];
|
$byCategory = [];
|
||||||
foreach ($controls as $ctrl) {
|
foreach ($controls as $ctrl) {
|
||||||
$cat = $ctrl['category'] ?? 'uncategorized';
|
$cat = $ctrl['framework'] ?? 'nis2';
|
||||||
if (!isset($byCategory[$cat])) {
|
if (!isset($byCategory[$cat])) {
|
||||||
$byCategory[$cat] = [
|
$byCategory[$cat] = [
|
||||||
'category' => $cat,
|
'category' => $cat,
|
||||||
'controls' => [],
|
'controls' => [],
|
||||||
'stats' => ['total' => 0, 'implemented' => 0, 'partial' => 0, 'planned' => 0, 'not_applicable' => 0],
|
'stats' => ['total' => 0, 'implemented' => 0, 'in_progress' => 0, 'not_started' => 0, 'verified' => 0],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
$byCategory[$cat]['controls'][] = $ctrl;
|
$byCategory[$cat]['controls'][] = $ctrl;
|
||||||
$byCategory[$cat]['stats']['total']++;
|
$byCategory[$cat]['stats']['total']++;
|
||||||
$s = $ctrl['status'] ?? 'not_applicable';
|
$s = $ctrl['status'] ?? 'not_started';
|
||||||
if (isset($byCategory[$cat]['stats'][$s])) {
|
if (isset($byCategory[$cat]['stats'][$s])) {
|
||||||
$byCategory[$cat]['stats'][$s]++;
|
$byCategory[$cat]['stats'][$s]++;
|
||||||
}
|
}
|
||||||
@ -1129,25 +1139,26 @@ class ServicesController extends BaseController
|
|||||||
// Score per categoria
|
// Score per categoria
|
||||||
foreach ($byCategory as &$cat) {
|
foreach ($byCategory as &$cat) {
|
||||||
$t = $cat['stats']['total'];
|
$t = $cat['stats']['total'];
|
||||||
$i = $cat['stats']['implemented'];
|
$i = $cat['stats']['implemented'] + ($cat['stats']['verified'] ?? 0);
|
||||||
$p = $cat['stats']['partial'];
|
$p = $cat['stats']['in_progress'] ?? 0;
|
||||||
$cat['score'] = $t > 0 ? round((($i + $p * 0.5) / $t) * 100) : 0;
|
$cat['score'] = $t > 0 ? round((($i + $p * 0.5) / $t) * 100) : 0;
|
||||||
}
|
}
|
||||||
unset($cat);
|
unset($cat);
|
||||||
|
|
||||||
$totals = [
|
$totals = [
|
||||||
'total' => count($controls),
|
'total' => count($controls),
|
||||||
'implemented' => 0,
|
'implemented' => 0,
|
||||||
'partial' => 0,
|
'verified' => 0,
|
||||||
'planned' => 0,
|
'in_progress' => 0,
|
||||||
'not_applicable' => 0,
|
'not_started' => 0,
|
||||||
];
|
];
|
||||||
foreach ($controls as $ctrl) {
|
foreach ($controls as $ctrl) {
|
||||||
$s = $ctrl['status'] ?? 'not_applicable';
|
$s = $ctrl['status'] ?? 'not_started';
|
||||||
if (isset($totals[$s])) $totals[$s]++;
|
if (isset($totals[$s])) $totals[$s]++;
|
||||||
}
|
}
|
||||||
|
$done = $totals['implemented'] + $totals['verified'];
|
||||||
$totals['overall_score'] = $totals['total'] > 0
|
$totals['overall_score'] = $totals['total'] > 0
|
||||||
? round((($totals['implemented'] + $totals['partial'] * 0.5) / $totals['total']) * 100)
|
? round((($done + $totals['in_progress'] * 0.5) / $totals['total']) * 100)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
$this->jsonSuccess([
|
$this->jsonSuccess([
|
||||||
@ -1191,7 +1202,7 @@ class ServicesController extends BaseController
|
|||||||
|
|
||||||
$assets = Database::fetchAll(
|
$assets = Database::fetchAll(
|
||||||
"SELECT id, name, asset_type, criticality, status,
|
"SELECT id, name, asset_type, criticality, status,
|
||||||
owner_name, location, ip_address, description,
|
owner_user_id, location, ip_address, description,
|
||||||
dependencies, created_at
|
dependencies, created_at
|
||||||
FROM assets
|
FROM assets
|
||||||
WHERE {$where}
|
WHERE {$where}
|
||||||
@ -1222,10 +1233,17 @@ class ServicesController extends BaseController
|
|||||||
$params = [$orgId];
|
$params = [$orgId];
|
||||||
|
|
||||||
if (!empty($_GET['risk_level'])) {
|
if (!empty($_GET['risk_level'])) {
|
||||||
|
// risk_score: 0-100, mappa high=>=60, critical=>=80
|
||||||
$levels = array_filter(explode(',', $_GET['risk_level']));
|
$levels = array_filter(explode(',', $_GET['risk_level']));
|
||||||
$ph = implode(',', array_fill(0, count($levels), '?'));
|
$conditions = [];
|
||||||
$where .= " AND s.risk_level IN ({$ph})";
|
foreach ($levels as $lv) {
|
||||||
$params = array_merge($params, $levels);
|
$lv = strtolower(trim($lv));
|
||||||
|
if ($lv === 'critical') { $conditions[] = 's.risk_score >= 80'; }
|
||||||
|
elseif ($lv === 'high') { $conditions[] = '(s.risk_score >= 60 AND s.risk_score < 80)'; }
|
||||||
|
elseif ($lv === 'medium') { $conditions[] = '(s.risk_score >= 30 AND s.risk_score < 60)'; }
|
||||||
|
elseif ($lv === 'low') { $conditions[] = 's.risk_score < 30'; }
|
||||||
|
}
|
||||||
|
if ($conditions) $where .= ' AND ('.implode(' OR ', $conditions).')';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($_GET['status'])) {
|
if (!empty($_GET['status'])) {
|
||||||
@ -1234,21 +1252,20 @@ class ServicesController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
$suppliers = Database::fetchAll(
|
$suppliers = Database::fetchAll(
|
||||||
"SELECT s.id, s.company_name, s.category, s.risk_level, s.status,
|
"SELECT s.id, s.name, s.service_type, s.criticality, s.risk_score, s.status,
|
||||||
s.last_assessment_date, s.assessment_score, s.contact_email,
|
s.last_assessment_date, s.contact_email,
|
||||||
s.services_provided, s.critical_dependency,
|
|
||||||
s.created_at, s.updated_at
|
s.created_at, s.updated_at
|
||||||
FROM suppliers s
|
FROM suppliers s
|
||||||
WHERE {$where}
|
WHERE {$where}
|
||||||
ORDER BY FIELD(s.risk_level,'critical','high','medium','low'), s.company_name",
|
ORDER BY FIELD(s.criticality,'critical','high','medium','low'), s.risk_score DESC, s.name",
|
||||||
$params
|
$params
|
||||||
);
|
);
|
||||||
|
|
||||||
$stats = Database::fetchOne(
|
$stats = Database::fetchOne(
|
||||||
"SELECT
|
"SELECT
|
||||||
COUNT(*) as total,
|
COUNT(*) as total,
|
||||||
SUM(CASE WHEN risk_level IN ('high','critical') AND deleted_at IS NULL THEN 1 ELSE 0 END) as high_risk,
|
SUM(CASE WHEN risk_score >= 60 AND deleted_at IS NULL THEN 1 ELSE 0 END) as high_risk,
|
||||||
SUM(CASE WHEN critical_dependency = 1 AND deleted_at IS NULL THEN 1 ELSE 0 END) as critical_deps,
|
SUM(CASE WHEN criticality IN ('critical','high') AND deleted_at IS NULL THEN 1 ELSE 0 END) as critical_deps,
|
||||||
SUM(CASE WHEN last_assessment_date IS NULL AND deleted_at IS NULL THEN 1 ELSE 0 END) as unassessed
|
SUM(CASE WHEN last_assessment_date IS NULL AND deleted_at IS NULL THEN 1 ELSE 0 END) as unassessed
|
||||||
FROM suppliers WHERE organization_id = ?",
|
FROM suppliers WHERE organization_id = ?",
|
||||||
[$orgId]
|
[$orgId]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user