getConnection()->prepare($sql); $stmt->execute(); $servers = $stmt->fetchAll(); View::render('layouts.admin', [ 'title' => 'Gerenciar Servidores', 'content' => __DIR__ . '/../../resources/views/admin/servers/index.php', 'servers' => $servers ]); } public function create() { $clientModel = new Client(); $clients = $clientModel->where('status', 'active'); View::render('layouts.admin', [ 'title' => 'Novo Servidor', 'content' => __DIR__ . '/../../resources/views/admin/servers/form.php', 'clients' => $clients ]); } public function store() { $clientModel = new Client(); $client = $clientModel->find($_POST['client_id']); if (!$client) { View::redirect('/admin/servers'); return; } // Validate IP vs ASN if (!ASNService::validateIP($_POST['ip_v4'], $client['asn'])) { $_SESSION['flash_error'] = "O IP informado não pertence ao ASN do cliente ({$client['asn']})."; // Keep input data $_SESSION['old_input'] = $_POST; View::redirect('/admin/servers/create'); return; } $data = [ 'client_id' => $_POST['client_id'], 'name' => $_POST['name'], 'ip_v4' => $_POST['ip_v4'], 'ip_v6' => $_POST['ip_v6'] ?? null, 'serial_key' => bin2hex(random_bytes(16)), 'status' => 'active' ]; $sql = "INSERT INTO servers (client_id, name, ip_v4, ip_v6, serial_key, status) VALUES (:client_id, :name, :ip_v4, :ip_v6, :serial_key, :status)"; $stmt = \App\Config\Database::getInstance()->getConnection()->prepare($sql); $stmt->execute($data); // Pangolin Integration - Sincroniza o cliente após adicionar servidor try { $pangolinService = new \App\Services\PangolinService(); if ($pangolinService->isEnabled() && $client['status'] === 'active') { $pangolinService->syncClient($_POST['client_id'], 'add'); } } catch (\Exception $e) { error_log("Pangolin Sync Error (Server Create): " . $e->getMessage()); } View::redirect('/admin/servers'); } public function edit($id) { $serverModel = new Server(); $server = $serverModel->find($id); if (!$server) { View::redirect('/admin/servers'); } $clientModel = new Client(); $clients = $clientModel->where('status', 'active'); View::render('layouts.admin', [ 'title' => 'Editar Servidor', 'content' => __DIR__ . '/../../resources/views/admin/servers/form.php', 'server' => $server, 'clients' => $clients ]); } public function update($id) { $serverModel = new Server(); $server = $serverModel->find($id); if (!$server) { View::redirect('/admin/servers'); return; } // If IP changed, validate again if ($_POST['ip_v4'] !== $server['ip_v4']) { $clientModel = new Client(); $client = $clientModel->find($_POST['client_id']); if (!ASNService::validateIP($_POST['ip_v4'], $client['asn'])) { $_SESSION['flash_error'] = "O IP informado não pertence ao ASN do cliente ({$client['asn']})."; View::redirect('/admin/servers/edit/' . $id); return; } } // Guardar IPs antigos para remover do Pangolin se mudaram $oldIpV4 = $server['ip_v4']; $oldIpV6 = $server['ip_v6']; $oldClientId = $server['client_id']; $oldStatus = $server['status']; $data = [ 'id' => $id, 'client_id' => $_POST['client_id'], 'name' => $_POST['name'], 'ip_v4' => $_POST['ip_v4'], 'ip_v6' => $_POST['ip_v6'] ?? null, 'status' => $_POST['status'] ]; $sql = "UPDATE servers SET client_id=:client_id, name=:name, ip_v4=:ip_v4, ip_v6=:ip_v6, status=:status WHERE id=:id"; $stmt = \App\Config\Database::getInstance()->getConnection()->prepare($sql); $stmt->execute($data); // Pangolin Integration - Sincroniza se IP, status ou cliente mudou try { $pangolinService = new \App\Services\PangolinService(); if ($pangolinService->isEnabled()) { $clientModel = new Client(); $client = $clientModel->find($_POST['client_id']); // Coletar IPs que mudaram para remover $ipsToRemove = []; if ($oldIpV4 !== $_POST['ip_v4']) { $ipsToRemove[] = $oldIpV4; } if ($oldIpV6 !== ($_POST['ip_v6'] ?? null)) { $ipsToRemove[] = $oldIpV6; } // Se o servidor era ativo e agora está inativo, remove os IPs if ($oldStatus === 'active' && $_POST['status'] === 'inactive') { $pangolinService->removeServerIps([$_POST['ip_v4'], $_POST['ip_v6'] ?? null]); } // Se o servidor era inativo e agora está ativo, adiciona os IPs elseif ($oldStatus === 'inactive' && $_POST['status'] === 'active') { if ($client && $client['status'] === 'active') { $pangolinService->syncClient($_POST['client_id'], 'add'); } } // Se os IPs mudaram elseif (!empty($ipsToRemove) && $_POST['status'] === 'active') { $pangolinService->removeServerIps($ipsToRemove); if ($client && $client['status'] === 'active') { $pangolinService->syncClient($_POST['client_id'], 'add'); } } // Se o cliente mudou, sincroniza o cliente antigo também if ($oldClientId != $_POST['client_id']) { $oldClient = $clientModel->find($oldClientId); if ($oldClient && $oldClient['status'] === 'active') { $pangolinService->removeServerIps([$oldIpV4, $oldIpV6]); } } } } catch (\Exception $e) { error_log("Pangolin Sync Error (Server Update): " . $e->getMessage()); } View::redirect('/admin/servers'); } public function delete($id) { $serverModel = new Server(); $server = $serverModel->find($id); if (!$server) { View::redirect('/admin/servers'); return; } // Capturar IPs antes de deletar $ipsToRemove = [$server['ip_v4']]; if (!empty($server['ip_v6'])) { $ipsToRemove[] = $server['ip_v6']; } // Pangolin Integration - Remove os IPs do servidor antes de deletá-lo try { $pangolinService = new \App\Services\PangolinService(); if ($pangolinService->isEnabled() && $server['status'] === 'active') { $clientModel = new Client(); $client = $clientModel->find($server['client_id']); if ($client && $client['status'] === 'active') { $pangolinService->removeServerIps($ipsToRemove); } } } catch (\Exception $e) { error_log("Pangolin Sync Error (Server Delete): " . $e->getMessage()); } // Delete the server $serverModel->delete($id); View::redirect('/admin/servers'); } public function resetMachineId($id) { $serverModel = new Server(); $server = $serverModel->find($id); if ($server) { $sql = "UPDATE servers SET machine_id = NULL WHERE id = :id"; $stmt = \App\Config\Database::getInstance()->getConnection()->prepare($sql); $stmt->execute(['id' => $id]); // Log action $logSql = "INSERT INTO api_logs (server_id, action, message, ip_address) VALUES (:sid, 'reset_machine', 'Machine ID reset by admin', :ip)"; $logStmt = \App\Config\Database::getInstance()->getConnection()->prepare($logSql); $logStmt->execute([ 'sid' => $id, 'ip' => $_SERVER['REMOTE_ADDR'] ?? null ]); } View::redirect('/admin/servers/edit/' . $id); } }