- New migration 002_server_access.sql: created_by column + server_user table - Server model: ownership, permission checks, team management methods - Routes: /team routes, RoleMiddleware on /servers/create and /admin - ServerController: permission checks via server_user, team CRUD methods - TerminalController: server access checks - DashboardController: filter servers by accessible ones - ApiController: server access checks - Views: team.php, team_server.php, sidebar Team link, hide actions by role - Default user role changed from operator to admin on registration - Admin user form defaults to admin role
143 lines
4.2 KiB
PHP
Executable File
143 lines
4.2 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace ServerManager\Controllers;
|
|
|
|
use ServerManager\Core\App;
|
|
use ServerManager\Core\Session;
|
|
use ServerManager\Models\Server;
|
|
use ServerManager\Services\SSHService;
|
|
use ServerManager\Services\AuditService;
|
|
use ServerManager\Models\CommandHistory;
|
|
|
|
class TerminalController
|
|
{
|
|
private \ServerManager\Core\View $view;
|
|
private Server $serverModel;
|
|
private AuditService $auditService;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->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.',
|
|
]);
|
|
}
|
|
}
|