From 8cee59a137b22c378a1d22cdd1b983c8e725307e Mon Sep 17 00:00:00 2001 From: Pedro Luis Date: Tue, 7 Jul 2026 09:51:15 -0300 Subject: [PATCH 1/3] Teste gitDusk 1 --- .env.example | 2 +- app/Http/Controllers/Auth/LoginController.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index d50429c..340f59b 100644 --- a/.env.example +++ b/.env.example @@ -59,7 +59,7 @@ FREERADIUS_MACADDR_CASE=lower CODIGO_ACESSO='ABCD-1234' SOMENTE_SENHAUNICA=false -USP_THEME_SKIN=uspdev +USP_THEME_SKIN=fflch # Dusk APP_URL=http://copaco diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 16e8d20..c959211 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -80,7 +80,7 @@ public function handleProviderCallback(Request $request) } } - + $login = true; if (!$login) { $request->session()->flash('alert-danger', 'Usuário sem acesso ao sistema.'); return redirect('/'); From 488c374816d7af681875651c163a70647ba56b94 Mon Sep 17 00:00:00 2001 From: Pedro Luis Date: Tue, 7 Jul 2026 10:00:30 -0300 Subject: [PATCH 2/3] =?UTF-8?q?Remo=C3=A7=C3=A3o=20do=20autenticador=20do?= =?UTF-8?q?=20loginController.php?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Auth/LoginController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index c959211..16e8d20 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -80,7 +80,7 @@ public function handleProviderCallback(Request $request) } } - $login = true; + if (!$login) { $request->session()->flash('alert-danger', 'Usuário sem acesso ao sistema.'); return redirect('/'); From d20d0fad4f85df19539de73d517fd11c43fe4c4f Mon Sep 17 00:00:00 2001 From: Pedro Luis Date: Wed, 8 Jul 2026 10:46:24 -0300 Subject: [PATCH 3/3] =?UTF-8?q?Implementa=C3=A7=C3=A3o=20do=20KeaDHCP=20no?= =?UTF-8?q?=20sistema=20e=20seu=20teste.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Api/KeaController.php | 278 +++++++++++++++++++++ resources/views/config/index.blade.php | 20 ++ routes/api.php | 4 + tests/Browser/RedeCrudTest.php | 6 + 4 files changed, 308 insertions(+) create mode 100644 app/Http/Controllers/Api/KeaController.php diff --git a/app/Http/Controllers/Api/KeaController.php b/app/Http/Controllers/Api/KeaController.php new file mode 100644 index 0000000..005c203 --- /dev/null +++ b/app/Http/Controllers/Api/KeaController.php @@ -0,0 +1,278 @@ +consumer_deploy_key != config('copaco.consumer_deploy_key')) { + return response()->json(['error' => 'Unauthorized action.'], 403); + } + + $date = Utils::ItensUpdatedAt(); + + $dhcp_global = Config::where('key', 'dhcp_global')->first(); + $globalOptions = $this->parseGlobalOptions($dhcp_global->value ?? ''); + + $keaConfig = [ + 'Dhcp4' => [ + 'interfaces-config' => [ + 'interfaces' => ['*'], // ou defina uma interface específica via config + ], + 'lease-database' => [ + 'type' => 'memfile', + 'name' => '/var/lib/kea/kea-leases4.csv', + ], + 'control-socket' => [ + 'socket-type' => 'unix', + 'socket-name' => '/tmp/kea4-ctrl-socket', + ], + 'loggers' => [ + [ + 'name' => 'kea-dhcp4', + 'severity' => 'INFO', + 'output_options' => [ + [ + 'output' => '/var/log/kea/kea-dhcp4.log', + ], + ], + ], + ], + 'option-data' => $globalOptions, // opções globais + 'shared-networks' => [], + ], + ]; + + $sharedNetworkConfig = Config::where('key', 'shared_network')->first(); + if (empty($sharedNetworkConfig)) { + // Todas as redes com active_dhcp=1 vão para a shared-network "default" + $redes = Rede::where('active_dhcp', 1)->get(); + if ($redes->isNotEmpty()) { + $keaConfig['Dhcp4']['shared-networks'][] = $this->buildSharedNetwork('default', $redes); + } + } else { + $sharedNetworksList = array_map('trim', explode(',', $sharedNetworkConfig->value)); + if (!in_array('default', $sharedNetworksList)) { + $sharedNetworksList[] = 'default'; + } + foreach ($sharedNetworksList as $sn) { + $redes = Rede::where('shared_network', $sn)->where('active_dhcp', 1)->get(); + if ($redes->isNotEmpty()) { + $keaConfig['Dhcp4']['shared-networks'][] = $this->buildSharedNetwork($sn, $redes); + } + } + } + + return response()->json($keaConfig, 200, ['Content-Type' => 'application/json']); + } + + private function buildSharedNetwork(string $name, $redes) + { + $sharedNetwork = [ + 'name' => $name, + 'subnet4' => [], + 'option-data' => [], + ]; + + foreach ($redes as $rede) { + $subnet = $this->buildSubnet($rede); + $sharedNetwork['subnet4'][] = $subnet; + } + + return $sharedNetwork; + } + + private function buildSubnet(Rede $rede) + { + $mask = (string) Network::parse("{$rede->iprede}/{$rede->cidr}")->netmask; + $subnetCidr = "{$rede->iprede}/{$rede->cidr}"; + + $rangeBegin = NetworkOps::findFirstIP($rede->iprede, $rede->cidr); + $rangeEnd = NetworkOps::findLastIP($rede->iprede, $rede->cidr); + $broadcast = NetworkOps::findBroadcast($rede->iprede, $rede->cidr); + + $options = []; + + $options[] = [ + 'name' => 'routers', + 'data' => $rede->gateway, + ]; + $options[] = [ + 'name' => 'broadcast-address', + 'data' => $broadcast, + ]; + if (!empty($rede->netbios)) { + $options[] = [ + 'name' => 'netbios-name-servers', + 'data' => $rede->netbios, + ]; + } + if (!empty($rede->ntp)) { + $options[] = [ + 'name' => 'ntp-servers', + 'data' => $rede->ntp, + ]; + } + if (!empty($rede->dns)) { + $options[] = [ + 'name' => 'domain-name-servers', + 'data' => $rede->dns, + ]; + } + if (!empty($rede->ad_domain)) { + $options[] = [ + 'name' => 'domain-name', + 'data' => $rede->ad_domain, + ]; + } + + if (!empty($rede->dhcpd_subnet_options)) { + + } + + // Reservas de host (equipamentos com IP fixo) + $reservations = []; + foreach ($rede->equipamentos as $equip) { + if (!empty($equip->macaddress) && !empty($equip->ip)) { + $reservations[] = [ + 'hw-address' => $equip->macaddress, + 'ip-address' => $equip->ip, + ]; + } + } + + $subnet = [ + 'subnet' => $subnetCidr, + 'pools' => [ + [ + 'pool' => "{$rangeBegin} - {$rangeEnd}", + ], + ], + 'option-data' => $options, + 'reservations' => $reservations, + ]; + + return $subnet; + } + + /** + * Converte as opções globais do dhcp_global para o formato Kea option-data + * Exemplo de entrada: "option domain-name-servers 8.8.8.8;\noption ntp-servers 0.0.0.0;" + */ + private function parseGlobalOptions($globalConfigText) + { + $options = []; + // Parse simplificado: procura linhas com "option ;" + $lines = explode("\n", $globalConfigText); + foreach ($lines as $line) { + if (preg_match('/^\s*option\s+([a-z0-9\-]+)\s+(.+?);\s*$/i', $line, $matches)) { + $name = $matches[1]; + $value = trim($matches[2]); + $options[] = [ + 'name' => $name, + 'data' => $value, + ]; + } + } + return $options; + } + + /** + * Geração de configuração Kea para rede única (não segmentada) + * Baseado em uniquedhcpd() + */ + public function uniquekeab(Request $request) + { + if ($request->consumer_deploy_key != config('copaco.consumer_deploy_key')) { + return response()->json(['error' => 'Unauthorized action.'], 403); + } + + $iprede = Config::where('key', 'unique_iprede')->first(); + $gateway = Config::where('key', 'unique_gateway')->first(); + $cidr = Config::where('key', 'unique_cidr')->first(); + + if (is_null($iprede) || is_null($gateway) || is_null($cidr)) { + return response()->json(['error' => 'Missing network data'], 403); + } + + $iprede = $iprede->value; + $gateway = $gateway->value; + $cidr = $cidr->value; + $mask = NetworkOps::findNetmask($cidr); + $broadcast = NetworkOps::findBroadcast($iprede, $cidr); + $rangeBegin = NetworkOps::findFirstIP($iprede, $cidr); + $rangeEnd = NetworkOps::findLastIP($iprede, $cidr); + + $ipsReservadosConfig = Config::where('key', 'ips_reservados')->first(); + $reservedIps = []; + if ($ipsReservadosConfig) { + $reservedIps = array_map('trim', explode(',', $ipsReservadosConfig->value)); + } + + $equipamentos = Equipamento::all(); + $reservations = []; + $ipsAlocados = $reservedIps; + foreach ($equipamentos as $equip) { + $ip = NetworkOps::nextIpAvailable($ipsAlocados, $iprede, $cidr, $gateway); + if ($ip && !empty($equip->macaddress)) { + $reservations[] = [ + 'hw-address' => $equip->macaddress, + 'ip-address' => $ip, + ]; + $ipsAlocados[] = $ip; + } + } + + $dhcp_global = Config::where('key', 'dhcp_global')->first(); + $globalOptions = $this->parseGlobalOptions($dhcp_global->value ?? ''); + + $keaConfig = [ + 'Dhcp4' => [ + 'interfaces-config' => ['interfaces' => ['*']], + 'lease-database' => [ + 'type' => 'memfile', + 'name' => '/var/lib/kea/kea-leases4.csv', + ], + 'control-socket' => [ + 'socket-type' => 'unix', + 'socket-name' => '/tmp/kea4-ctrl-socket', + ], + 'loggers' => [ + [ + 'name' => 'kea-dhcp4', + 'severity' => 'INFO', + 'output_options' => [ + ['output' => '/var/log/kea/kea-dhcp4.log'], + ], + ], + ], + 'option-data' => $globalOptions, + 'subnet4' => [ + [ + 'subnet' => "{$iprede}/{$cidr}", + 'pools' => [ + ['pool' => "{$rangeBegin} - {$rangeEnd}"], + ], + 'option-data' => [ + ['name' => 'routers', 'data' => $gateway], + ['name' => 'broadcast-address', 'data' => $broadcast], + ], + 'reservations' => $reservations, + ], + ], + ], + ]; + + return response()->json($keaConfig, 200, ['Content-Type' => 'application/json']); + } +} \ No newline at end of file diff --git a/resources/views/config/index.blade.php b/resources/views/config/index.blade.php index 81736e6..5886370 100644 --- a/resources/views/config/index.blade.php +++ b/resources/views/config/index.blade.php @@ -5,6 +5,26 @@ @stop @section('content') +
+
+ {{csrf_field()}} + + +
+
+ +
+ +
+
+ {{csrf_field()}} + + +
+
+ +
+
{{csrf_field()}} diff --git a/routes/api.php b/routes/api.php index 98b205a..dfe4503 100644 --- a/routes/api.php +++ b/routes/api.php @@ -2,7 +2,11 @@ use App\Http\Controllers\Api\DhcpController; use App\Http\Controllers\Api\FreeradiusController; +use App\Http\Controllers\Api\EquipamentoController; +use App\Http\Controllers\Api\KeaController; Route::post('/dhcpd.conf', [DhcpController::class, 'dhcpd']); Route::post('/uniquedhcpd.conf', [DhcpController::class, 'uniquedhcpd']); Route::post('/freeradius/authorize_file', [FreeradiusController::class, 'authorize_file']); +Route::post('/kea', [KeaController::class, 'kea']); +Route::post('/kea/unique', [KeaController::class, 'uniquekeab']); diff --git a/tests/Browser/RedeCrudTest.php b/tests/Browser/RedeCrudTest.php index 2c3b587..a702cf8 100644 --- a/tests/Browser/RedeCrudTest.php +++ b/tests/Browser/RedeCrudTest.php @@ -53,6 +53,12 @@ public function test_rede_crud() ->pause(1000) ->assertSee('Rede Teste Editada'); + // Gerar Keadhcp + $browser->visit("/config") + ->press('Gerar configuração Kea (JSON) - Redes segmentadas') + ->pause(2000) + ->assertSee('141.232.67.1'); + // Delete $browser->visit('/redes') ->click("form[action$='/redes/{$rede->id}'] button.delete-item")