safeLoad(); // Build container $containerBuilder = new ContainerBuilder(); $containerBuilder->addDefinitions([ 'settings' => [ 'db' => [ 'host' => getenv('DB_HOST') ?: 'db', 'port' => (int)(getenv('DB_PORT') ?: 3306), 'database' => getenv('DB_DATABASE') ?: 'domovoy', 'username' => getenv('DB_USERNAME') ?: 'domovoy', 'password' => getenv('DB_PASSWORD') ?: 'domovoy', ], 'app' => [ 'env' => getenv('APP_ENV') ?: 'development', 'secret' => getenv('APP_SECRET') ?: 'change-me', 'encryption_key' => getenv('ENCRYPTION_KEY') ?: '', ], 'ssh' => [ 'connect_timeout' => (int)(getenv('SSH_CONNECT_TIMEOUT_SECONDS') ?: 5), 'auth_timeout' => (int)(getenv('SSH_AUTH_TIMEOUT_SECONDS') ?: 10), 'command_timeout' => (int)(getenv('SSH_COMMAND_TIMEOUT_SECONDS') ?: 8), 'total_scan_timeout' => (int)(getenv('SSH_TOTAL_SCAN_TIMEOUT_SECONDS') ?: 60), 'retry_count' => (int)(getenv('SSH_RETRY_COUNT') ?: 0), ], ], 'logger' => function () { $logger = new \Monolog\Logger('domovoy'); $logger->pushHandler(new \Monolog\Handler\StreamHandler( dirname(__DIR__) . '/storage/logs/app.log', \Monolog\Level::Debug )); return $logger; }, PDO::class => function ($c) { $db = $c->get('settings')['db']; $dsn = sprintf( 'mysql:host=%s;port=%d;dbname=%s;charset=utf8mb4', $db['host'], $db['port'], $db['database'] ); return new PDO($dsn, $db['username'], $db['password'], [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]); }, // Repositories \Domovoy\Repositories\UserRepository::class => function ($c) { return new \Domovoy\Repositories\UserRepository($c->get(PDO::class)); }, \Domovoy\Repositories\NetworkRangeRepository::class => function ($c) { return new \Domovoy\Repositories\NetworkRangeRepository($c->get(PDO::class)); }, \Domovoy\Repositories\ScanJobRepository::class => function ($c) { return new \Domovoy\Repositories\ScanJobRepository($c->get(PDO::class)); }, \Domovoy\Repositories\DiscoveredHostRepository::class => function ($c) { return new \Domovoy\Repositories\DiscoveredHostRepository($c->get(PDO::class)); }, \Domovoy\Repositories\CredentialRepository::class => function ($c) { return new \Domovoy\Repositories\CredentialRepository($c->get(PDO::class)); }, \Domovoy\Repositories\AuditLogRepository::class => function ($c) { return new \Domovoy\Repositories\AuditLogRepository($c->get(PDO::class)); }, // Discovery services \Domovoy\Services\Discovery\PingScanner::class => function () { return new \Domovoy\Services\Discovery\PingScanner(); }, \Domovoy\Services\Discovery\TcpPortScanner::class => function () { return new \Domovoy\Services\Discovery\TcpPortScanner(); }, \Domovoy\Services\Discovery\ArpTableReader::class => function () { return new \Domovoy\Services\Discovery\ArpTableReader(); }, \Domovoy\Services\Discovery\HostFingerprintService::class => function () { return new \Domovoy\Services\Discovery\HostFingerprintService(); }, \Domovoy\Services\Discovery\NetworkScanner::class => function ($c) { return new \Domovoy\Services\Discovery\NetworkScanner( $c->get(\Domovoy\Services\Discovery\PingScanner::class), $c->get(\Domovoy\Services\Discovery\TcpPortScanner::class), $c->get(\Domovoy\Services\Discovery\ArpTableReader::class), $c->get(\Domovoy\Services\Discovery\HostFingerprintService::class), $c->get(\Domovoy\Repositories\DiscoveredHostRepository::class) ); }, // Job runner \Domovoy\Services\Jobs\ScanJobRunner::class => function ($c) { return new \Domovoy\Services\Jobs\ScanJobRunner( $c->get(\Domovoy\Repositories\ScanJobRepository::class), $c->get(\Domovoy\Services\Discovery\NetworkScanner::class), $c->get(\Domovoy\Repositories\NetworkRangeRepository::class) ); }, // Auth \Domovoy\Services\AuthService::class => function ($c) { return new \Domovoy\Services\AuthService($c->get(\Domovoy\Repositories\UserRepository::class)); }, \Domovoy\Services\Security\CredentialVault::class => function ($c) { return new \Domovoy\Services\Security\CredentialVault($c->get('settings')['app']['encryption_key']); }, \Domovoy\Services\Ssh\SshCredentialTester::class => function ($c) { return new \Domovoy\Services\Ssh\SshCredentialTester( $c->get(\Domovoy\Services\Security\CredentialVault::class), null, $c->get('settings')['ssh'] ); }, // Controllers \Domovoy\Controllers\AuthController::class => function ($c) { return new \Domovoy\Controllers\AuthController($c->get(\Domovoy\Services\AuthService::class)); }, \Domovoy\Controllers\SetupController::class => function ($c) { return new \Domovoy\Controllers\SetupController($c->get(\Domovoy\Services\AuthService::class)); }, \Domovoy\Controllers\DashboardController::class => function ($c) { return new \Domovoy\Controllers\DashboardController( $c->get(\Domovoy\Repositories\DeviceRepository::class), $c->get(\Domovoy\Repositories\ScanJobRepository::class) ); }, \Domovoy\Controllers\DiscoveryController::class => function ($c) { return new \Domovoy\Controllers\DiscoveryController( $c->get(\Domovoy\Repositories\NetworkRangeRepository::class), $c->get(\Domovoy\Repositories\ScanJobRepository::class), $c->get(\Domovoy\Repositories\DiscoveredHostRepository::class) ); }, \Domovoy\Controllers\NetworkRangeController::class => function ($c) { return new \Domovoy\Controllers\NetworkRangeController( $c->get(\Domovoy\Repositories\NetworkRangeRepository::class) ); }, // Inventory \Domovoy\Repositories\DeviceRepository::class => function ($c) { return new \Domovoy\Repositories\DeviceRepository($c->get(PDO::class)); }, \Domovoy\Services\Inventory\DeviceService::class => function ($c) { return new \Domovoy\Services\Inventory\DeviceService( $c->get(\Domovoy\Repositories\DeviceRepository::class), $c->get(\Domovoy\Repositories\DiscoveredHostRepository::class) ); }, \Domovoy\Services\Inventory\MergeSuggestionService::class => function ($c) { return new \Domovoy\Services\Inventory\MergeSuggestionService($c->get(\Domovoy\Repositories\DeviceRepository::class)); }, \Domovoy\Controllers\DeviceController::class => function ($c) { return new \Domovoy\Controllers\DeviceController( $c->get(\Domovoy\Services\Inventory\DeviceService::class), $c->get(\Domovoy\Repositories\DiscoveredHostRepository::class), $c->get(\Domovoy\Repositories\CredentialRepository::class) ); }, \Domovoy\Controllers\CredentialController::class => function ($c) { return new \Domovoy\Controllers\CredentialController( $c->get(\Domovoy\Services\Inventory\DeviceService::class), $c->get(\Domovoy\Repositories\CredentialRepository::class), $c->get(\Domovoy\Services\Security\CredentialVault::class), $c->get(\Domovoy\Services\Ssh\SshCredentialTester::class) ); }, \Domovoy\Controllers\DiscoveriesController::class => function ($c) { return new \Domovoy\Controllers\DiscoveriesController( $c->get(\Domovoy\Repositories\DiscoveredHostRepository::class), $c->get(\Domovoy\Repositories\NetworkRangeRepository::class), $c->get(\Domovoy\Services\Inventory\DeviceService::class) ); }, ]); $container = $containerBuilder->build(); // Build Slim app AppFactory::setContainer($container); $app = AppFactory::create(); $app->addRoutingMiddleware(); $app->addBodyParsingMiddleware(); $app->add(new \Domovoy\Middleware\AuthMiddleware()); $app->addErrorMiddleware(true, true, true); // Public routes $app->get('/login', [\Domovoy\Controllers\AuthController::class, 'loginForm'])->setName('login'); $app->post('/login', [\Domovoy\Controllers\AuthController::class, 'login'])->setName('login.post'); $app->get('/setup', [\Domovoy\Controllers\SetupController::class, 'form'])->setName('setup'); $app->post('/setup', [\Domovoy\Controllers\SetupController::class, 'create'])->setName('setup.post'); // Protected routes $app->group('', function (\Slim\Routing\RouteCollectorProxy $group) { $group->get('/dashboard', [\Domovoy\Controllers\DashboardController::class, 'index'])->setName('dashboard'); $group->post('/logout', [\Domovoy\Controllers\AuthController::class, 'logout'])->setName('logout'); // Discovery $group->get('/discovery', [\Domovoy\Controllers\DiscoveryController::class, 'index'])->setName('discovery'); $group->post('/discovery/scan', [\Domovoy\Controllers\DiscoveryController::class, 'startScan'])->setName('discovery.scan'); $group->post('/discovery/hosts/ignore', [\Domovoy\Controllers\DiscoveryController::class, 'ignoreHost'])->setName('discovery.hosts.ignore'); $group->get('/discovery/jobs/active', [\Domovoy\Controllers\DiscoveryController::class, 'activeJobs'])->setName('discovery.jobs.active'); $group->get('/discovery/jobs/history', [\Domovoy\Controllers\DiscoveryController::class, 'scanHistory'])->setName('discovery.jobs.history'); $group->post('/discovery/jobs/{id}/pause', [\Domovoy\Controllers\DiscoveryController::class, 'pauseJob'])->setName('discovery.jobs.pause'); $group->post('/discovery/jobs/{id}/resume', [\Domovoy\Controllers\DiscoveryController::class, 'resumeJob'])->setName('discovery.jobs.resume'); $group->post('/discovery/jobs/{id}/cancel', [\Domovoy\Controllers\DiscoveryController::class, 'cancelJob'])->setName('discovery.jobs.cancel'); // Discoveries $group->get('/discoveries', [\Domovoy\Controllers\DiscoveriesController::class, 'index'])->setName('discoveries'); $group->get('/discoveries/table', [\Domovoy\Controllers\DiscoveriesController::class, 'table'])->setName('discoveries.table'); $group->post('/discoveries/merge', [\Domovoy\Controllers\DiscoveriesController::class, 'merge'])->setName('discoveries.merge'); // Network ranges CRUD $group->post('/discovery/ranges/create', [\Domovoy\Controllers\NetworkRangeController::class, 'create'])->setName('discovery.ranges.create'); $group->post('/discovery/ranges/toggle', [\Domovoy\Controllers\NetworkRangeController::class, 'toggle'])->setName('discovery.ranges.toggle'); $group->post('/discovery/ranges/delete', [\Domovoy\Controllers\NetworkRangeController::class, 'delete'])->setName('discovery.ranges.delete'); // Devices CRUD $group->get('/devices', [\Domovoy\Controllers\DeviceController::class, 'index'])->setName('devices'); $group->get('/devices/create', [\Domovoy\Controllers\DeviceController::class, 'createForm'])->setName('devices.create'); $group->post('/devices/create', [\Domovoy\Controllers\DeviceController::class, 'create'])->setName('devices.create.post'); $group->get('/devices/{id}', [\Domovoy\Controllers\DeviceController::class, 'show'])->setName('devices.show'); $group->get('/devices/{id}/edit', [\Domovoy\Controllers\DeviceController::class, 'editForm'])->setName('devices.edit'); $group->post('/devices/{id}/update', [\Domovoy\Controllers\DeviceController::class, 'update'])->setName('devices.update'); $group->post('/devices/{id}/delete', [\Domovoy\Controllers\DeviceController::class, 'delete'])->setName('devices.delete'); $group->post('/devices/from-host', [\Domovoy\Controllers\DeviceController::class, 'createFromHost'])->setName('devices.from_host'); $group->post('/devices/{id}/credentials', [\Domovoy\Controllers\CredentialController::class, 'create'])->setName('credentials.create'); $group->post('/devices/{deviceId}/credentials/{id}/test', [\Domovoy\Controllers\CredentialController::class, 'test'])->setName('credentials.test'); $group->post('/devices/{deviceId}/credentials/{id}/delete', [\Domovoy\Controllers\CredentialController::class, 'delete'])->setName('credentials.delete'); }); $app->run();