ServerManager project files
This commit is contained in:
166
src/Controllers/AdminController.php
Executable file
166
src/Controllers/AdminController.php
Executable file
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ServerManager\Controllers;
|
||||
|
||||
use ServerManager\Core\App;
|
||||
use ServerManager\Core\Session;
|
||||
use ServerManager\Core\Validator;
|
||||
use ServerManager\Models\User;
|
||||
use ServerManager\Services\AuditService;
|
||||
|
||||
class AdminController
|
||||
{
|
||||
private \ServerManager\Core\View $view;
|
||||
private User $userModel;
|
||||
private AuditService $auditService;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->view = App::getInstance()->getView();
|
||||
$this->userModel = new User();
|
||||
$this->auditService = new AuditService();
|
||||
}
|
||||
|
||||
public function users(): void
|
||||
{
|
||||
$page = (int) ($_GET['page'] ?? 1);
|
||||
$users = $this->userModel->getAll($page, 20);
|
||||
|
||||
$this->view->display('admin.users', [
|
||||
'title' => 'User Management - ServerManager',
|
||||
'users' => $users,
|
||||
]);
|
||||
}
|
||||
|
||||
public function createUser(): void
|
||||
{
|
||||
$validator = new Validator();
|
||||
$rules = [
|
||||
'username' => 'required|min:3|max:50|alphaNum',
|
||||
'email' => 'required|email',
|
||||
'password' => 'required|min:8',
|
||||
'role' => 'required|in:super_admin,admin,operator',
|
||||
];
|
||||
|
||||
if (!$validator->validate($_POST, $rules)) {
|
||||
$this->view->json(['success' => false, 'message' => $validator->getFirstError()]);
|
||||
}
|
||||
|
||||
$existingUser = $this->userModel->findByUsername($_POST['username']);
|
||||
if ($existingUser) {
|
||||
$this->view->json(['success' => false, 'message' => 'Username already exists.']);
|
||||
}
|
||||
|
||||
$existingEmail = $this->userModel->findByEmail($_POST['email']);
|
||||
if ($existingEmail) {
|
||||
$this->view->json(['success' => false, 'message' => 'Email already exists.']);
|
||||
}
|
||||
|
||||
$id = $this->userModel->create([
|
||||
'username' => $_POST['username'],
|
||||
'email' => $_POST['email'],
|
||||
'password' => $_POST['password'],
|
||||
'role' => $_POST['role'],
|
||||
'is_active' => 1,
|
||||
]);
|
||||
|
||||
$this->auditService->logUserManagement($id, 'user_created');
|
||||
|
||||
$this->view->json([
|
||||
'success' => true,
|
||||
'message' => 'User created successfully.',
|
||||
'user_id' => $id,
|
||||
]);
|
||||
}
|
||||
|
||||
public function updateUser(int $id): void
|
||||
{
|
||||
$user = $this->userModel->findById($id);
|
||||
|
||||
if (!$user) {
|
||||
$this->view->json(['success' => false, 'message' => 'User not found'], 404);
|
||||
}
|
||||
|
||||
$updateData = [];
|
||||
|
||||
if (!empty($_POST['email'])) {
|
||||
$updateData['email'] = $_POST['email'];
|
||||
}
|
||||
|
||||
if (!empty($_POST['role'])) {
|
||||
$updateData['role'] = $_POST['role'];
|
||||
}
|
||||
|
||||
if (!empty($_POST['password'])) {
|
||||
$updateData['password'] = $_POST['password'];
|
||||
}
|
||||
|
||||
if (isset($_POST['is_active'])) {
|
||||
$updateData['is_active'] = (int) $_POST['is_active'];
|
||||
}
|
||||
|
||||
if (empty($updateData)) {
|
||||
$this->view->json(['success' => false, 'message' => 'No data to update.']);
|
||||
}
|
||||
|
||||
$this->userModel->update($id, $updateData);
|
||||
|
||||
$this->auditService->logUserManagement($id, 'user_updated');
|
||||
|
||||
$this->view->json([
|
||||
'success' => true,
|
||||
'message' => 'User updated successfully.',
|
||||
]);
|
||||
}
|
||||
|
||||
public function deleteUser(int $id): void
|
||||
{
|
||||
$user = $this->userModel->findById($id);
|
||||
|
||||
if (!$user) {
|
||||
$this->view->json(['success' => false, 'message' => 'User not found'], 404);
|
||||
}
|
||||
|
||||
if ($user['id'] === Session::get('user_id')) {
|
||||
$this->view->json(['success' => false, 'message' => 'You cannot delete your own account.']);
|
||||
}
|
||||
|
||||
$this->userModel->delete($id);
|
||||
|
||||
$this->auditService->logUserManagement($id, 'user_deleted');
|
||||
|
||||
$this->view->json([
|
||||
'success' => true,
|
||||
'message' => 'User deleted successfully.',
|
||||
]);
|
||||
}
|
||||
|
||||
public function auditLogs(): void
|
||||
{
|
||||
$page = (int) ($_GET['page'] ?? 1);
|
||||
$action = $_GET['action'] ?? '';
|
||||
$userId = $_GET['user_id'] ?? '';
|
||||
|
||||
$filters = [];
|
||||
if ($action) $filters['action'] = $action;
|
||||
if ($userId) $filters['user_id'] = (int) $userId;
|
||||
|
||||
$logs = $this->auditService->getAuditLogs($page, 50, $filters);
|
||||
|
||||
$this->view->display('admin.audit', [
|
||||
'title' => 'Audit Logs - ServerManager',
|
||||
'logs' => $logs,
|
||||
'action' => $action,
|
||||
'userId' => $userId,
|
||||
]);
|
||||
}
|
||||
|
||||
public function securitySettings(): void
|
||||
{
|
||||
$this->view->display('admin.security', [
|
||||
'title' => 'Security Settings - ServerManager',
|
||||
]);
|
||||
}
|
||||
}
|
||||
283
src/Controllers/ApiController.php
Executable file
283
src/Controllers/ApiController.php
Executable file
@@ -0,0 +1,283 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ServerManager\Controllers;
|
||||
|
||||
use ServerManager\Core\App;
|
||||
use ServerManager\Core\Session;
|
||||
use ServerManager\Core\Validator;
|
||||
use ServerManager\Models\Server;
|
||||
use ServerManager\Models\User;
|
||||
use ServerManager\Services\MonitoringService;
|
||||
use ServerManager\Services\SSHService;
|
||||
use ServerManager\Services\AuditService;
|
||||
use ServerManager\Models\CommandHistory;
|
||||
|
||||
class ApiController
|
||||
{
|
||||
private \ServerManager\Core\View $view;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->view = App::getInstance()->getView();
|
||||
}
|
||||
|
||||
private function authenticateRequest(): ?array
|
||||
{
|
||||
$token = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
|
||||
$token = str_replace('Bearer ', '', $token);
|
||||
|
||||
if (empty($token) && isset($_GET['api_token'])) {
|
||||
$token = $_GET['api_token'];
|
||||
}
|
||||
|
||||
if (empty($token)) {
|
||||
$this->view->json(['error' => 'API token is required'], 401);
|
||||
}
|
||||
|
||||
$userModel = new User();
|
||||
$user = $userModel->findByApiToken($token);
|
||||
|
||||
if (!$user) {
|
||||
$this->view->json(['error' => 'Invalid API token'], 401);
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function status(): void
|
||||
{
|
||||
$this->authenticateRequest();
|
||||
|
||||
$monitoringService = new MonitoringService();
|
||||
$stats = $monitoringService->getDashboardStats();
|
||||
|
||||
$this->view->json([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'application' => 'ServerManager',
|
||||
'version' => '1.0.0',
|
||||
'stats' => $stats,
|
||||
'timestamp' => date('c'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function servers(): void
|
||||
{
|
||||
$user = $this->authenticateRequest();
|
||||
|
||||
$serverModel = new Server();
|
||||
$page = (int) ($_GET['page'] ?? 1);
|
||||
$perPage = (int) ($_GET['per_page'] ?? 20);
|
||||
$search = $_GET['search'] ?? '';
|
||||
|
||||
$filters = [];
|
||||
if ($search) $filters['search'] = $search;
|
||||
|
||||
$servers = $serverModel->getAll($page, $perPage, $filters);
|
||||
|
||||
$this->view->json([
|
||||
'success' => true,
|
||||
'data' => $servers['data'],
|
||||
'pagination' => [
|
||||
'page' => $servers['page'],
|
||||
'per_page' => $servers['per_page'],
|
||||
'total' => $servers['total'],
|
||||
'total_pages' => $servers['total_pages'],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function serverDetail(int $id): void
|
||||
{
|
||||
$user = $this->authenticateRequest();
|
||||
|
||||
$serverModel = new Server();
|
||||
$server = $serverModel->findById($id);
|
||||
|
||||
if (!$server) {
|
||||
$this->view->json(['error' => 'Server not found'], 404);
|
||||
}
|
||||
|
||||
$monitoringService = new MonitoringService();
|
||||
$metrics = $monitoringService->getLatestMetrics($id);
|
||||
|
||||
$this->view->json([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'server' => $server,
|
||||
'metrics' => $metrics,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function serverAdd(): void
|
||||
{
|
||||
$user = $this->authenticateRequest();
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?? $_POST;
|
||||
|
||||
$validator = new Validator();
|
||||
$rules = [
|
||||
'name' => 'required|min:2|max:100',
|
||||
'ip_address' => 'required',
|
||||
'ssh_port' => 'required|numeric|port',
|
||||
'ssh_user' => 'required|min:2|max:50',
|
||||
];
|
||||
|
||||
if (!$validator->validate($input, $rules)) {
|
||||
$this->view->json(['error' => $validator->getFirstError()], 400);
|
||||
}
|
||||
|
||||
$serverModel = new Server();
|
||||
$id = $serverModel->create($input);
|
||||
|
||||
$this->view->json([
|
||||
'success' => true,
|
||||
'message' => 'Server created successfully.',
|
||||
'server_id' => $id,
|
||||
], 201);
|
||||
}
|
||||
|
||||
public function serverUpdate(int $id): void
|
||||
{
|
||||
$user = $this->authenticateRequest();
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?? $_POST;
|
||||
|
||||
$serverModel = new Server();
|
||||
$server = $serverModel->findById($id);
|
||||
|
||||
if (!$server) {
|
||||
$this->view->json(['error' => 'Server not found'], 404);
|
||||
}
|
||||
|
||||
$serverModel->update($id, $input);
|
||||
|
||||
$this->view->json([
|
||||
'success' => true,
|
||||
'message' => 'Server updated successfully.',
|
||||
]);
|
||||
}
|
||||
|
||||
public function serverDelete(int $id): void
|
||||
{
|
||||
$user = $this->authenticateRequest();
|
||||
|
||||
$serverModel = new Server();
|
||||
$server = $serverModel->findById($id);
|
||||
|
||||
if (!$server) {
|
||||
$this->view->json(['error' => 'Server not found'], 404);
|
||||
}
|
||||
|
||||
$serverModel->delete($id);
|
||||
|
||||
$this->view->json([
|
||||
'success' => true,
|
||||
'message' => 'Server deleted successfully.',
|
||||
]);
|
||||
}
|
||||
|
||||
public function serverMetrics(int $id): void
|
||||
{
|
||||
$user = $this->authenticateRequest();
|
||||
|
||||
$monitoringService = new MonitoringService();
|
||||
|
||||
$hours = (int) ($_GET['hours'] ?? 24);
|
||||
if ($hours > 168) $hours = 168;
|
||||
|
||||
$metrics = $monitoringService->getHistoricalMetrics($id, $hours);
|
||||
|
||||
$this->view->json([
|
||||
'success' => true,
|
||||
'data' => $metrics,
|
||||
]);
|
||||
}
|
||||
|
||||
public function executeCommand(int $id): void
|
||||
{
|
||||
$user = $this->authenticateRequest();
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?? $_POST;
|
||||
$command = $input['command'] ?? '';
|
||||
|
||||
if (empty($command)) {
|
||||
$this->view->json(['error' => 'Command is required'], 400);
|
||||
}
|
||||
|
||||
$serverModel = new Server();
|
||||
$server = $serverModel->findById($id);
|
||||
|
||||
if (!$server) {
|
||||
$this->view->json(['error' => 'Server not found'], 404);
|
||||
}
|
||||
|
||||
try {
|
||||
$ssh = new SSHService();
|
||||
if (!$ssh->connect($server)) {
|
||||
throw new \RuntimeException('Could not establish SSH connection');
|
||||
}
|
||||
$result = $ssh->exec($command);
|
||||
$ssh->disconnect();
|
||||
|
||||
$commandHistory = new CommandHistory();
|
||||
$commandHistory->log(
|
||||
$id,
|
||||
$user['id'],
|
||||
$command,
|
||||
$result['output'],
|
||||
$result['exit_status'] ?? 0
|
||||
);
|
||||
|
||||
$auditService = new AuditService();
|
||||
$auditService->logServerAction($id, 'api_command_executed', $command);
|
||||
|
||||
$this->view->json([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'output' => $result['output'],
|
||||
'exit_status' => $result['exit_status'],
|
||||
'stderr' => $result['stderr'],
|
||||
],
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
$this->view->json([
|
||||
'error' => 'Command execution failed: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function users(): void
|
||||
{
|
||||
$currentUser = $this->authenticateRequest();
|
||||
|
||||
if ($currentUser['role'] !== 'super_admin' && $currentUser['role'] !== 'admin') {
|
||||
$this->view->json(['error' => 'Forbidden'], 403);
|
||||
}
|
||||
|
||||
$userModel = new User();
|
||||
$users = $userModel->getAll(1, 100);
|
||||
|
||||
$this->view->json([
|
||||
'success' => true,
|
||||
'data' => $users['data'],
|
||||
]);
|
||||
}
|
||||
|
||||
public function refreshAllMetrics(): void
|
||||
{
|
||||
$user = $this->authenticateRequest();
|
||||
|
||||
$monitoringService = new MonitoringService();
|
||||
$results = $monitoringService->collectAllMetrics();
|
||||
|
||||
$this->view->json([
|
||||
'success' => true,
|
||||
'data' => $results,
|
||||
]);
|
||||
}
|
||||
}
|
||||
149
src/Controllers/AuthController.php
Executable file
149
src/Controllers/AuthController.php
Executable file
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ServerManager\Controllers;
|
||||
|
||||
use ServerManager\Core\App;
|
||||
use ServerManager\Core\Session;
|
||||
use ServerManager\Core\Validator;
|
||||
use ServerManager\Models\User;
|
||||
use ServerManager\Services\AuditService;
|
||||
|
||||
class AuthController
|
||||
{
|
||||
private User $userModel;
|
||||
private AuditService $auditService;
|
||||
private \ServerManager\Core\View $view;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->userModel = new User();
|
||||
$this->auditService = new AuditService();
|
||||
$this->view = App::getInstance()->getView();
|
||||
}
|
||||
|
||||
public function loginForm(): void
|
||||
{
|
||||
if (Session::has('user_id')) {
|
||||
$this->view->redirect('/dashboard');
|
||||
}
|
||||
|
||||
$this->view->setLayout('auth');
|
||||
$this->view->display('auth.login', [
|
||||
'title' => 'Login - ServerManager',
|
||||
]);
|
||||
}
|
||||
|
||||
public function login(): void
|
||||
{
|
||||
$validator = new Validator();
|
||||
$rules = [
|
||||
'username' => 'required',
|
||||
'password' => 'required|min:6',
|
||||
];
|
||||
|
||||
if (!$validator->validate($_POST, $rules)) {
|
||||
$error = $validator->getFirstError();
|
||||
$this->auditService->logLogin($_POST['username'] ?? 'unknown', false, $error);
|
||||
Session::setFlash('error', $error);
|
||||
$this->view->redirect('/login');
|
||||
}
|
||||
|
||||
$username = $_POST['username'];
|
||||
$password = $_POST['password'];
|
||||
|
||||
$user = $this->userModel->authenticate($username, $password);
|
||||
|
||||
if (!$user) {
|
||||
$this->auditService->logLogin($username, false, 'Invalid credentials');
|
||||
Session::setFlash('error', 'Invalid username or password.');
|
||||
$this->view->redirect('/login');
|
||||
}
|
||||
|
||||
Session::regenerate(true);
|
||||
|
||||
Session::set('user_id', $user['id']);
|
||||
Session::set('username', $user['username']);
|
||||
Session::set('user_role', $user['role']);
|
||||
Session::set('user_email', $user['email']);
|
||||
Session::set('login_time', time());
|
||||
|
||||
$lifetime = App::getConfig()['session']['lifetime'] ?? 1440;
|
||||
Session::set('session_expiry', time() + $lifetime);
|
||||
|
||||
$this->auditService->logLogin($username, true);
|
||||
|
||||
$intended = Session::get('intended_url', '/dashboard');
|
||||
Session::remove('intended_url');
|
||||
|
||||
$this->view->redirect($intended);
|
||||
}
|
||||
|
||||
public function logout(): void
|
||||
{
|
||||
$this->auditService->log(
|
||||
'logout',
|
||||
'user',
|
||||
Session::get('user_id'),
|
||||
['username' => Session::get('username')]
|
||||
);
|
||||
|
||||
Session::destroy();
|
||||
$this->view->redirect('/login');
|
||||
}
|
||||
|
||||
public function profile(): void
|
||||
{
|
||||
$userId = Session::get('user_id');
|
||||
$user = $this->userModel->findById($userId);
|
||||
|
||||
if (!$user) {
|
||||
$this->view->error(404);
|
||||
}
|
||||
|
||||
$this->view->display('auth.profile', [
|
||||
'title' => 'My Profile - ServerManager',
|
||||
'user' => $user,
|
||||
]);
|
||||
}
|
||||
|
||||
public function updateProfile(): void
|
||||
{
|
||||
$userId = Session::get('user_id');
|
||||
|
||||
$validator = new Validator();
|
||||
$rules = [
|
||||
'email' => 'required|email',
|
||||
'current_password' => 'required',
|
||||
'new_password' => 'min:8',
|
||||
'confirm_password' => 'match:new_password',
|
||||
];
|
||||
|
||||
if (!$validator->validate($_POST, $rules)) {
|
||||
Session::setFlash('error', $validator->getFirstError());
|
||||
$this->view->redirect('/profile');
|
||||
}
|
||||
|
||||
$user = $this->userModel->findById($userId);
|
||||
|
||||
$security = new \ServerManager\Core\Security();
|
||||
if (!$security->verifyPassword($_POST['current_password'], $user['password_hash'])) {
|
||||
Session::setFlash('error', 'Current password is incorrect.');
|
||||
$this->view->redirect('/profile');
|
||||
}
|
||||
|
||||
$updateData = ['email' => $_POST['email']];
|
||||
|
||||
if (!empty($_POST['new_password'])) {
|
||||
$updateData['password'] = $_POST['new_password'];
|
||||
}
|
||||
|
||||
$this->userModel->update($userId, $updateData);
|
||||
|
||||
$this->auditService->logUserManagement($userId, 'profile_updated');
|
||||
|
||||
Session::setFlash('success', 'Profile updated successfully.');
|
||||
$this->view->redirect('/profile');
|
||||
}
|
||||
}
|
||||
60
src/Controllers/DashboardController.php
Executable file
60
src/Controllers/DashboardController.php
Executable file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ServerManager\Controllers;
|
||||
|
||||
use ServerManager\Core\App;
|
||||
use ServerManager\Models\Server;
|
||||
use ServerManager\Services\MonitoringService;
|
||||
use ServerManager\Services\AuditService;
|
||||
|
||||
class DashboardController
|
||||
{
|
||||
private \ServerManager\Core\View $view;
|
||||
private MonitoringService $monitoringService;
|
||||
private AuditService $auditService;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->view = App::getInstance()->getView();
|
||||
$this->monitoringService = new MonitoringService();
|
||||
$this->auditService = new AuditService();
|
||||
}
|
||||
|
||||
public function index(): void
|
||||
{
|
||||
$stats = $this->monitoringService->getDashboardStats();
|
||||
$recentActivity = $this->auditService->getRecentActivity(10);
|
||||
|
||||
$serverModel = new Server();
|
||||
$servers = $serverModel->findAll(true);
|
||||
|
||||
$this->view->display('dashboard.index', [
|
||||
'title' => 'Dashboard - ServerManager',
|
||||
'stats' => $stats,
|
||||
'servers' => $servers,
|
||||
'recentActivity' => $recentActivity,
|
||||
]);
|
||||
}
|
||||
|
||||
public function stats(): void
|
||||
{
|
||||
$stats = $this->monitoringService->getDashboardStats();
|
||||
|
||||
$this->view->json([
|
||||
'success' => true,
|
||||
'data' => $stats,
|
||||
]);
|
||||
}
|
||||
|
||||
public function refreshMetrics(): void
|
||||
{
|
||||
$this->monitoringService->collectAllMetrics();
|
||||
|
||||
$this->view->json([
|
||||
'success' => true,
|
||||
'message' => 'Metrics refreshed',
|
||||
]);
|
||||
}
|
||||
}
|
||||
1488
src/Controllers/ServerController.php
Executable file
1488
src/Controllers/ServerController.php
Executable file
File diff suppressed because it is too large
Load Diff
132
src/Controllers/TerminalController.php
Executable file
132
src/Controllers/TerminalController.php
Executable file
@@ -0,0 +1,132 @@
|
||||
<?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);
|
||||
}
|
||||
|
||||
$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);
|
||||
}
|
||||
|
||||
$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.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user