view = App::getInstance()->getView(); $this->serverModel = new Server(); $this->auditService = new AuditService(); } public function index(int $id): void { $server = $this->serverModel->findById($id); if (!$server) { $this->view->error(404); } $userId = (int) Session::get('user_id'); if (!$this->serverModel->canView($id, $userId)) { $this->view->error(404); } $commandHistory = new CommandHistory(); $history = $commandHistory->getByServer($id, 50); $this->view->display('terminal.index', [ 'title' => 'Terminal - ' . $server['name'] . ' - ServerManager', 'server' => $server, 'commandHistory' => $history, ]); } public function execute(int $id): void { $server = $this->serverModel->findById($id); if (!$server) { $this->view->json(['success' => false, 'message' => 'Server not found'], 404); } $userId = (int) Session::get('user_id'); if (!$this->serverModel->canView($id, $userId)) { $this->view->json(['success' => false, 'message' => 'Forbidden'], 403); } $command = $_POST['command'] ?? ''; if (empty($command)) { $this->view->json(['success' => false, 'message' => 'Command is required']); } $blockedCommands = ['rm -rf /', 'mkfs', 'dd if=', ':(){ :|:& };:']; foreach ($blockedCommands as $blocked) { if (stripos($command, $blocked) !== false) { $this->auditService->log('blocked_command', 'server', $id, [ 'command' => $command, 'reason' => 'Blocked dangerous command pattern', ]); $this->view->json([ 'success' => false, 'message' => 'This command has been blocked for safety reasons.', ]); } } try { $ssh = new SSHService(); if (!$ssh->connect($server)) { throw new \RuntimeException('Could not establish SSH connection'); } $this->auditService->logCredentialAccess($id, 'Terminal command execution'); $result = $ssh->exec($command); $ssh->disconnect(); $commandHistory = new CommandHistory(); $commandHistory->log( $id, Session::get('user_id'), $command, $result['output'], $result['exit_status'] ?? 0 ); $this->auditService->logServerAction($id, 'command_executed', $command); $this->view->json([ 'success' => true, 'output' => $result['output'], 'exit_status' => $result['exit_status'], 'stderr' => $result['stderr'], ]); } catch (\Throwable $e) { $this->view->json([ 'success' => false, 'message' => 'Failed to execute command: ' . $e->getMessage(), ]); } } public function history(int $id): void { $commandHistory = new CommandHistory(); $history = $commandHistory->getByServer($id, 100); $this->view->json([ 'success' => true, 'data' => $history, ]); } public function clearHistory(int $id): void { $commandHistory = new CommandHistory(); $commandHistory->clearHistory($id); $this->auditService->log('command_history_cleared', 'server', $id); $this->view->json([ 'success' => true, 'message' => 'Command history cleared.', ]); } }