- Agregar validación multi-capa para garantizar IPs 100% disponibles - Capa 1: Filtrar IPs de dispositivos registrados en UISP - Capa 2: Filtrar IPs de servicios CRM suspendidos/finalizados (449 IPs) - Capa 3: Validar IPs usando búsqueda de sitios con type=subscriber - Capa 4: Verificación opcional por ping para dispositivos de terceros Nuevos Componentes: - src/IpValidator.php: Clase de validación por búsqueda de sitios - Validación progresiva en frontend JavaScript - Endpoint action=validate en public.php Mejoras: - CrmService.php: Filtrado mejorado de servicios suspendidos/finalizados - IpSearchService.php: Extraer todas las IPs de ipAddressList - Frontend: Validación progresiva de IPs con feedback visual - Cambiar suspended=false a suspended=true en API de UISP Correcciones: - Corregir variable $config indefinida en handler de validación - Corregir falsos positivos agregando parámetro type=subscriber - Corregir IPs secundarias no detectadas - Corregir IPs de servicios suspendidos/finalizados mostrándose disponibles Resultados de Pruebas: - IP 172.16.54.70 (servicio finalizado): Filtrada correctamente por capa CRM - IP 172.16.54.58 (cliente activo): Filtrada correctamente por búsqueda de sitios - Todas las IPs mostradas verificadas como 100% disponibles Documentación: - Actualizado README.md con detalles del sistema de 4 capas - Actualizado CHANGELOG.md con notas de versión 1.6.0 - Creado walkthrough.md completo
157 lines
5.4 KiB
PHP
157 lines
5.4 KiB
PHP
<?php
|
|
|
|
namespace SiipAvailableIps;
|
|
|
|
/**
|
|
* Validador de IPs usando búsqueda de sitios en UISP
|
|
* Utiliza el endpoint /sites/search para encontrar dispositivos por IP
|
|
*/
|
|
class IpValidator
|
|
{
|
|
private $baseUrl;
|
|
private $apiToken;
|
|
private $logger;
|
|
|
|
public function __construct($baseUrl, $apiToken, $logger = null)
|
|
{
|
|
$this->baseUrl = rtrim($baseUrl, '/');
|
|
$this->apiToken = $apiToken;
|
|
$this->logger = $logger;
|
|
}
|
|
|
|
/**
|
|
* Verifica si una IP está en uso en UISP usando búsqueda de sitios
|
|
*
|
|
* @param string $ip IP a verificar
|
|
* @return bool True si la IP está en uso, false si está disponible
|
|
*/
|
|
public function isIpInUse($ip)
|
|
{
|
|
try {
|
|
// 1. Buscar sitio por IP usando el endpoint de búsqueda
|
|
// IMPORTANTE: type=subscriber solo busca en sitios de clientes (endpoints)
|
|
$searchUrl = $this->baseUrl . '/nms/api/v2.1/sites/search?query=' . urlencode($ip) . '&count=1&page=1&type=subscriber';
|
|
|
|
if ($this->logger) {
|
|
$this->logger->appendLog("IpValidator: Buscando sitio para IP $ip");
|
|
}
|
|
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $searchUrl);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
|
'X-Auth-Token: ' . $this->apiToken
|
|
]);
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
|
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($httpCode !== 200) {
|
|
if ($this->logger) {
|
|
$this->logger->appendLog("IpValidator: Error HTTP $httpCode al buscar sitio");
|
|
}
|
|
return false; // Si hay error, asumir que no está en uso
|
|
}
|
|
|
|
$sites = json_decode($response, true);
|
|
|
|
// Si no hay sitios, la IP no está en uso
|
|
if (empty($sites) || !isset($sites[0]['id'])) {
|
|
if ($this->logger) {
|
|
$this->logger->appendLog("IpValidator: No se encontró sitio para IP $ip - DISPONIBLE");
|
|
}
|
|
return false;
|
|
}
|
|
|
|
$siteId = $sites[0]['id'];
|
|
|
|
if ($this->logger) {
|
|
$this->logger->appendLog("IpValidator: Sitio encontrado: $siteId");
|
|
}
|
|
|
|
// 2. Obtener dispositivos del sitio
|
|
$devicesUrl = $this->baseUrl . '/nms/api/v2.1/devices?siteId=' . $siteId;
|
|
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $devicesUrl);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
|
'X-Auth-Token: ' . $this->apiToken
|
|
]);
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
|
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($httpCode !== 200) {
|
|
if ($this->logger) {
|
|
$this->logger->appendLog("IpValidator: Error HTTP $httpCode al obtener dispositivos");
|
|
}
|
|
return false;
|
|
}
|
|
|
|
$devices = json_decode($response, true);
|
|
|
|
// 3. Verificar si algún dispositivo tiene la IP
|
|
foreach ($devices as $device) {
|
|
// Verificar IP principal
|
|
if (isset($device['ipAddress'])) {
|
|
$deviceIp = explode('/', $device['ipAddress'])[0];
|
|
if ($deviceIp === $ip) {
|
|
if ($this->logger) {
|
|
$this->logger->appendLog("IpValidator: IP $ip encontrada en dispositivo (ipAddress) - EN USO");
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Verificar lista de IPs
|
|
if (isset($device['ipAddressList']) && is_array($device['ipAddressList'])) {
|
|
if (in_array($ip, $device['ipAddressList'])) {
|
|
if ($this->logger) {
|
|
$this->logger->appendLog("IpValidator: IP $ip encontrada en dispositivo (ipAddressList) - EN USO");
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($this->logger) {
|
|
$this->logger->appendLog("IpValidator: IP $ip no encontrada en dispositivos del sitio - DISPONIBLE");
|
|
}
|
|
|
|
return false;
|
|
|
|
} catch (\Exception $e) {
|
|
if ($this->logger) {
|
|
$this->logger->appendLog("IpValidator: Excepción: " . $e->getMessage());
|
|
}
|
|
return false; // En caso de error, asumir disponible
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Valida un lote de IPs y devuelve las que están en uso
|
|
*
|
|
* @param array $ips Array de IPs a validar
|
|
* @return array Array de IPs que están en uso
|
|
*/
|
|
public function getIpsInUse(array $ips)
|
|
{
|
|
$ipsInUse = [];
|
|
|
|
foreach ($ips as $ip) {
|
|
if ($this->isIpInUse($ip)) {
|
|
$ipsInUse[] = $ip;
|
|
}
|
|
}
|
|
|
|
return $ipsInUse;
|
|
}
|
|
}
|