From 8cee59a137b22c378a1d22cdd1b983c8e725307e Mon Sep 17 00:00:00 2001 From: Pedro Luis Date: Tue, 7 Jul 2026 09:51:15 -0300 Subject: [PATCH 1/6] 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/6] =?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/6] =?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") From 650fcd642b1d38eebd13aecb9b169f176139b5ee Mon Sep 17 00:00:00 2001 From: Pedro Luis Date: Wed, 5 Aug 2026 15:05:49 -0300 Subject: [PATCH 4/6] -m "commit inicial" --- app/Http/Controllers/Api/KeaController.php | 2 - app/Http/Services/keaServices.php | 230 +++++++++++++++++++++ 2 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 app/Http/Services/keaServices.php diff --git a/app/Http/Controllers/Api/KeaController.php b/app/Http/Controllers/Api/KeaController.php index 005c203..e8b4c29 100644 --- a/app/Http/Controllers/Api/KeaController.php +++ b/app/Http/Controllers/Api/KeaController.php @@ -23,7 +23,6 @@ public function kea(Request $request) $dhcp_global = Config::where('key', 'dhcp_global')->first(); $globalOptions = $this->parseGlobalOptions($dhcp_global->value ?? ''); - $keaConfig = [ 'Dhcp4' => [ 'interfaces-config' => [ @@ -49,7 +48,6 @@ public function kea(Request $request) ], ], 'option-data' => $globalOptions, // opções globais - 'shared-networks' => [], ], ]; diff --git a/app/Http/Services/keaServices.php b/app/Http/Services/keaServices.php new file mode 100644 index 0000000..c6e569a --- /dev/null +++ b/app/Http/Services/keaServices.php @@ -0,0 +1,230 @@ +parseGlobalOptions(); + + if ($unique) { + $reservation = $this->getReservation(); + } + + $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 + ], + ]; + + return $keaConfig; + } + + public 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) + { + $dhcp_global = Config::where('key', 'dhcp_global')->first(); + + if(empty($dhcp_global)) return null; + + $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; + } + + + public static SharedNetwork() { + $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 $sharedNetworkConfig; + } + + private function getReservation() { + $sharedNetworkConfig = KeaService::sharedNetwork(); + $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; + } + } + return $reservation; + } +} + From 9c1c5e8cbecff9bc436a89160ed12bd9ce980720 Mon Sep 17 00:00:00 2001 From: Pedro Luis Date: Fri, 14 Aug 2026 09:48:18 -0300 Subject: [PATCH 5/6] =?UTF-8?q?Separando=20C=C3=B3digos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Api/KeaController.php | 264 ++---------------- app/Http/Controllers/Auth/LoginController.php | 1 + app/Http/Services/KeaService.php | 223 +++++++++++++++ app/Http/Services/keaServices.php | 230 --------------- 4 files changed, 241 insertions(+), 477 deletions(-) create mode 100644 app/Http/Services/KeaService.php delete mode 100644 app/Http/Services/keaServices.php diff --git a/app/Http/Controllers/Api/KeaController.php b/app/Http/Controllers/Api/KeaController.php index e8b4c29..c669f21 100644 --- a/app/Http/Controllers/Api/KeaController.php +++ b/app/Http/Controllers/Api/KeaController.php @@ -4,273 +4,43 @@ use App\Http\Controllers\Controller; use Illuminate\Http\Request; -use App\Models\Rede; -use App\Models\Equipamento; -use App\Models\Config; -use App\Utils\NetworkOps; -use App\Utils\Utils; -use IPTools\Network; +use App\Http\Services\KeaService; class KeaController extends Controller { - public function kea(Request $request) - { - if ($request->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 - ], - ]; - - $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']); - } + protected $keaService; - private function buildSharedNetwork(string $name, $redes) + public function __construct(KeaService $keaService) { - $sharedNetwork = [ - 'name' => $name, - 'subnet4' => [], - 'option-data' => [], - ]; - - foreach ($redes as $rede) { - $subnet = $this->buildSubnet($rede); - $sharedNetwork['subnet4'][] = $subnet; - } - - return $sharedNetwork; + $this->keaService = $keaService; } - private function buildSubnet(Rede $rede) + public function kea(Request $request) { - $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)) { - + if ($request->consumer_deploy_key != config('copaco.consumer_deploy_key')) { + return response()->json(['error' => 'Unauthorized action.'], 403); } - // 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, - ]; - } + try { + $config = $this->keaService->generateKeaConfig(); + return response()->json($config, 200, ['Content-Type' => 'application/json']); + } catch (\Exception $e) { + return response()->json(['error' => $e->getMessage()], 500); } - - $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; - } + try { + $config = $this->keaService->generateUniqueKeaConfig(); + return response()->json($config, 200, ['Content-Type' => 'application/json']); + } catch (\Exception $e) { + return response()->json(['error' => $e->getMessage()], 500); } - - $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/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 16e8d20..cfb3cc2 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -80,6 +80,7 @@ public function handleProviderCallback(Request $request) } } + $login = true; if (!$login) { $request->session()->flash('alert-danger', 'Usuário sem acesso ao sistema.'); diff --git a/app/Http/Services/KeaService.php b/app/Http/Services/KeaService.php new file mode 100644 index 0000000..1d2f08d --- /dev/null +++ b/app/Http/Services/KeaService.php @@ -0,0 +1,223 @@ + [ + 'interfaces-config' => [ + 'interfaces' => ['*'], // pode vir de config futuramente + ], + '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' => [], // será preenchido depois + ], + ]; + } + + public function generateKeaConfig(): array + { + $config = $this->baseConfig(); + $config['Dhcp4']['option-data'] = $this->parseGlobalOptions(); + + $sharedNetworkConfig = Config::where('key', 'shared_network')->first(); + + if (empty($sharedNetworkConfig)) { + $redes = Rede::where('active_dhcp', 1)->get(); + if ($redes->isNotEmpty()) { + $config['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()) { + $config['Dhcp4']['shared-networks'][] = $this->buildSharedNetwork($sn, $redes); + } + } + } + + return $config; + } + + + public function generateUniqueKeaConfig(): array + { + $config = $this->baseConfig(); + $config['Dhcp4']['option-data'] = $this->parseGlobalOptions(); + + $iprede = Config::where('key', 'unique_iprede')->value('value'); + $gateway = Config::where('key', 'unique_gateway')->value('value'); + $cidr = Config::where('key', 'unique_cidr')->value('value'); + + if (!$iprede || !$gateway || !$cidr) { + throw new \Exception('Missing network data for unique configuration'); + } + + $broadcast = NetworkOps::findBroadcast($iprede, $cidr); + $rangeBegin = NetworkOps::findFirstIP($iprede, $cidr); + $rangeEnd = NetworkOps::findLastIP($iprede, $cidr); + + // Opções específicas da subnet + $subnetOptions = [ + ['name' => 'routers', 'data' => $gateway], + ['name' => 'broadcast-address', 'data' => $broadcast], + ]; + + // Reservas para equipamentos (alocação automática) + $reservations = $this->buildReservationsForUnique($iprede, $cidr, $gateway); + + $config['Dhcp4']['subnet4'] = [ + [ + 'subnet' => "{$iprede}/{$cidr}", + 'pools' => [ + ['pool' => "{$rangeBegin} - {$rangeEnd}"], + ], + 'option-data' => $subnetOptions, + 'reservations' => $reservations, + ], + ]; + + return $config; + } + + + private function buildSharedNetwork(string $name, $redes): array + { + $sharedNetwork = [ + 'name' => $name, + 'subnet4' => [], + 'option-data' => [], // opções comuns a todas subnets (se houver) + ]; + + foreach ($redes as $rede) { + $sharedNetwork['subnet4'][] = $this->buildSubnet($rede); + } + + return $sharedNetwork; + } + + private function buildSubnet(Rede $rede): array + { + $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); + + // Opções DHCP para esta subnet + $options = [ + ['name' => 'routers', 'data' => $rede->gateway], + ['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]; + } + + + $reservations = []; + foreach ($rede->equipamentos as $equip) { + if (!empty($equip->macaddress) && !empty($equip->ip)) { + $reservations[] = [ + 'hw-address' => $equip->macaddress, + 'ip-address' => $equip->ip, + ]; + } + } + + return [ + 'subnet' => $subnetCidr, + 'pools' => [ + ['pool' => "{$rangeBegin} - {$rangeEnd}"], + ], + 'option-data' => $options, + 'reservations' => $reservations, + ]; + } + + private function buildReservationsForUnique(string $iprede, string $cidr, string $gateway): array + { + $reservedIpsConfig = Config::where('key', 'ips_reservados')->first(); + $reservedIps = $reservedIpsConfig ? array_map('trim', explode(',', $reservedIpsConfig->value)) : []; + + $equipamentos = Equipamento::all(); + $reservations = []; + $ipsAlocados = $reservedIps; + + foreach ($equipamentos as $equip) { + if (empty($equip->macaddress)) { + continue; + } + $ip = NetworkOps::nextIpAvailable($ipsAlocados, $iprede, $cidr, $gateway); + if ($ip) { + $reservations[] = [ + 'hw-address' => $equip->macaddress, + 'ip-address' => $ip, + ]; + $ipsAlocados[] = $ip; + } + } + + return $reservations; + } + + private function parseGlobalOptions(): array + { + $dhcpGlobal = Config::where('key', 'dhcp_global')->first(); + if (!$dhcpGlobal || empty($dhcpGlobal->value)) { + return []; + } + + $options = []; + $lines = explode("\n", $dhcpGlobal->value); + foreach ($lines as $line) { + if (preg_match('/^\s*option\s+([a-z0-9\-]+)\s+(.+?);\s*$/i', $line, $matches)) { + $options[] = [ + 'name' => $matches[1], + 'data' => trim($matches[2]), + ]; + } + } + return $options; + } +} \ No newline at end of file diff --git a/app/Http/Services/keaServices.php b/app/Http/Services/keaServices.php deleted file mode 100644 index c6e569a..0000000 --- a/app/Http/Services/keaServices.php +++ /dev/null @@ -1,230 +0,0 @@ -parseGlobalOptions(); - - if ($unique) { - $reservation = $this->getReservation(); - } - - $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 - ], - ]; - - return $keaConfig; - } - - public 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) - { - $dhcp_global = Config::where('key', 'dhcp_global')->first(); - - if(empty($dhcp_global)) return null; - - $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; - } - - - public static SharedNetwork() { - $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 $sharedNetworkConfig; - } - - private function getReservation() { - $sharedNetworkConfig = KeaService::sharedNetwork(); - $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; - } - } - return $reservation; - } -} - From f1486f666d0d0fe0d23563d7f6ff47913a623671 Mon Sep 17 00:00:00 2001 From: Pedro Luis Date: Fri, 14 Aug 2026 09:49:57 -0300 Subject: [PATCH 6/6] =?UTF-8?q?Remo=C3=A7=C3=A3o=20importante=20do=20login?= =?UTF-8?q?Controller?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Auth/LoginController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index cfb3cc2..16e8d20 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -80,7 +80,6 @@ public function handleProviderCallback(Request $request) } } - $login = true; if (!$login) { $request->session()->flash('alert-danger', 'Usuário sem acesso ao sistema.');