requireOrgAccess(); $pagination = $this->getPagination(); $where = 'organization_id = ?'; $params = [$this->getCurrentOrgId()]; if ($this->hasParam('asset_type')) { $where .= ' AND asset_type = ?'; $params[] = $this->getParam('asset_type'); } if ($this->hasParam('criticality')) { $where .= ' AND criticality = ?'; $params[] = $this->getParam('criticality'); } if ($this->hasParam('status')) { $where .= ' AND status = ?'; $params[] = $this->getParam('status'); } $total = Database::count('assets', $where, $params); $assets = Database::fetchAll( "SELECT a.*, u.full_name as owner_name FROM assets a LEFT JOIN users u ON u.id = a.owner_user_id WHERE a.{$where} ORDER BY a.criticality DESC, a.name LIMIT {$pagination['per_page']} OFFSET {$pagination['offset']}", $params ); $this->jsonPaginated($assets, $total, $pagination['page'], $pagination['per_page']); } public function create(): void { $this->requireOrgRole(['org_admin', 'compliance_manager']); $this->validateRequired(['name', 'asset_type']); $assetId = Database::insert('assets', [ 'organization_id' => $this->getCurrentOrgId(), 'name' => trim($this->getParam('name')), 'asset_type' => $this->getParam('asset_type'), 'category' => $this->getParam('category'), 'description' => $this->getParam('description'), 'criticality' => $this->getParam('criticality', 'medium'), 'owner_user_id' => $this->getParam('owner_user_id'), 'location' => $this->getParam('location'), 'ip_address' => $this->getParam('ip_address'), 'vendor' => $this->getParam('vendor'), 'version' => $this->getParam('version'), 'serial_number' => $this->getParam('serial_number'), 'purchase_date' => $this->getParam('purchase_date'), 'warranty_expiry' => $this->getParam('warranty_expiry'), 'dependencies' => $this->getParam('dependencies') ? json_encode($this->getParam('dependencies')) : null, ]); $this->logAudit('asset_created', 'asset', $assetId); $this->jsonSuccess(['id' => $assetId], 'Asset registrato', 201); } public function get(int $id): void { $this->requireOrgAccess(); $asset = Database::fetchOne( 'SELECT a.*, u.full_name as owner_name FROM assets a LEFT JOIN users u ON u.id = a.owner_user_id WHERE a.id = ? AND a.organization_id = ?', [$id, $this->getCurrentOrgId()] ); if (!$asset) { $this->jsonError('Asset non trovato', 404, 'ASSET_NOT_FOUND'); } $this->jsonSuccess($asset); } public function update(int $id): void { $this->requireOrgRole(['org_admin', 'compliance_manager']); $updates = []; $fields = ['name', 'asset_type', 'category', 'description', 'criticality', 'owner_user_id', 'location', 'ip_address', 'vendor', 'version', 'serial_number', 'purchase_date', 'warranty_expiry', 'status']; foreach ($fields as $field) { if ($this->hasParam($field)) { $updates[$field] = $this->getParam($field); } } if ($this->hasParam('dependencies')) { $updates['dependencies'] = json_encode($this->getParam('dependencies')); } if (!empty($updates)) { Database::update('assets', $updates, 'id = ? AND organization_id = ?', [$id, $this->getCurrentOrgId()]); $this->logAudit('asset_updated', 'asset', $id, $updates); } $this->jsonSuccess($updates, 'Asset aggiornato'); } public function delete(int $id): void { $this->requireOrgRole(['org_admin']); $deleted = Database::delete('assets', 'id = ? AND organization_id = ?', [$id, $this->getCurrentOrgId()]); if ($deleted === 0) { $this->jsonError('Asset non trovato', 404, 'ASSET_NOT_FOUND'); } $this->logAudit('asset_deleted', 'asset', $id); $this->jsonSuccess(null, 'Asset eliminato'); } public function dependencyMap(): void { $this->requireOrgAccess(); $assets = Database::fetchAll( 'SELECT id, name, asset_type, criticality, dependencies FROM assets WHERE organization_id = ? AND status = "active"', [$this->getCurrentOrgId()] ); $nodes = []; $edges = []; foreach ($assets as $asset) { $nodes[] = [ 'id' => $asset['id'], 'label' => $asset['name'], 'type' => $asset['asset_type'], 'criticality' => $asset['criticality'], ]; $deps = json_decode($asset['dependencies'] ?? '[]', true) ?: []; foreach ($deps as $depId) { $edges[] = ['from' => $asset['id'], 'to' => (int) $depId]; } } $this->jsonSuccess(['nodes' => $nodes, 'edges' => $edges]); } }