nis2-agile/application/controllers/AdminController.php
Cristiano Benassati ae78a2f7f4 [CORE] Initial project scaffold - NIS2 Agile Compliance Platform
Complete MVP implementation including:
- PHP 8.4 backend with Front Controller pattern (80+ API endpoints)
- Multi-tenant architecture with organization_id isolation
- JWT authentication (HS256, 2h access + 7d refresh tokens)
- 14 controllers: Auth, Organization, Assessment, Dashboard, Risk,
  Incident, Policy, SupplyChain, Training, Asset, Audit, Admin
- AI Service integration (Anthropic Claude API) for gap analysis,
  risk suggestions, policy generation, incident classification
- NIS2 gap analysis questionnaire (~80 questions, 10 categories)
- MySQL schema (20 tables) with NIS2 Art. 21 compliance controls
- NIS2 Art. 23 incident reporting workflow (24h/72h/30d)
- Frontend: login, register, dashboard, assessment wizard, org setup
- Docker configuration (PHP-FPM + Nginx + MySQL)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:50:18 +01:00

72 lines
2.9 KiB
PHP

<?php
/**
* NIS2 Agile - Admin Controller
*
* Gestione piattaforma (solo super_admin).
*/
require_once __DIR__ . '/BaseController.php';
class AdminController extends BaseController
{
public function listOrganizations(): void
{
$this->requireSuperAdmin();
$pagination = $this->getPagination();
$total = Database::count('organizations', '1=1');
$orgs = Database::fetchAll(
"SELECT o.*,
(SELECT COUNT(*) FROM user_organizations WHERE organization_id = o.id) as member_count,
(SELECT overall_score FROM assessments WHERE organization_id = o.id AND status = 'completed' ORDER BY completed_at DESC LIMIT 1) as last_score
FROM organizations o
ORDER BY o.created_at DESC
LIMIT {$pagination['per_page']} OFFSET {$pagination['offset']}"
);
$this->jsonPaginated($orgs, $total, $pagination['page'], $pagination['per_page']);
}
public function listUsers(): void
{
$this->requireSuperAdmin();
$pagination = $this->getPagination();
$total = Database::count('users', '1=1');
$users = Database::fetchAll(
"SELECT u.id, u.email, u.full_name, u.role, u.is_active, u.last_login_at, u.created_at,
GROUP_CONCAT(o.name) as organizations
FROM users u
LEFT JOIN user_organizations uo ON uo.user_id = u.id
LEFT JOIN organizations o ON o.id = uo.organization_id
GROUP BY u.id
ORDER BY u.created_at DESC
LIMIT {$pagination['per_page']} OFFSET {$pagination['offset']}"
);
$this->jsonPaginated($users, $total, $pagination['page'], $pagination['per_page']);
}
public function platformStats(): void
{
$this->requireSuperAdmin();
$this->jsonSuccess([
'total_organizations' => Database::count('organizations', '1=1'),
'active_organizations' => Database::count('organizations', 'is_active = 1'),
'total_users' => Database::count('users', '1=1'),
'active_users' => Database::count('users', 'is_active = 1'),
'total_assessments' => Database::count('assessments', '1=1'),
'completed_assessments' => Database::count('assessments', 'status = "completed"'),
'total_incidents' => Database::count('incidents', '1=1'),
'open_incidents' => Database::count('incidents', 'status NOT IN ("closed", "post_mortem")'),
'total_risks' => Database::count('risks', '1=1'),
'total_policies' => Database::count('policies', '1=1'),
'ai_interactions' => Database::count('ai_interactions', '1=1'),
'plans_distribution' => Database::fetchAll(
'SELECT subscription_plan, COUNT(*) as count FROM organizations GROUP BY subscription_plan'
),
]);
}
}