appendLog('POST update_password recibido: ' . var_export($_POST, true)); // lógica PATCH $result = updateClientPasswordAttribute($_POST['clientId'], $_POST['password']); $logger->appendLog('Resultado updateClientPasswordAttribute: ' . var_export($result, true)); header('Content-Type: application/json'); echo json_encode($result); exit; } use GuzzleHttp\Client; use GuzzleHttp\Exception\RequestException; chdir(__DIR__); require_once __DIR__ . '/vendor/autoload.php'; // --- ENDPOINT PARA ACTUALIZAR CONTRASEÑA DEL CLIENTE --- if (isset($_POST['update_password']) && isset($_POST['clientId']) && isset($_POST['password'])) { $logger = \Ubnt\UcrmPluginSdk\Service\PluginLogManager::create(); $logger->appendLog('POST update_password recibido: ' . var_export($_POST, true)); $clientId = $_POST['clientId']; $password = $_POST['password']; $result = updateClientPasswordAttribute($clientId, $password); $logger->appendLog('Resultado updateClientPasswordAttribute: ' . var_export($result, true)); header('Content-Type: application/json'); echo json_encode($result); exit; } // Get UCRM log manager. $log = \Ubnt\UcrmPluginSdk\Service\PluginLogManager::create(); // $log->appendLog( // sprintf( // 'Executed from public URL: %s', // file_get_contents('php://input') // ) // ); // Variable para almacenar la respuesta de la API, mensajes de error y estado $respuestaAPI = ''; $esError = false; $clientFullName = ''; $IpAddressClientId = ''; $clientIdentifierType = 'ID'; // Puede ser 'ID', 'IP', 'MAC' //variables para mostrar info del cliente $clientFullName = ''; $IpAddressClientId = ''; // Ensure global variables are initialized at the top of the script $clientFullName = $clientFullName ?? ''; $IpAddressClientId = $IpAddressClientId ?? ''; // Verificar si se ha enviado el formulario if ($_SERVER['REQUEST_METHOD'] === 'POST') { /** * Actualiza el atributo personalizado 'passwordAntenaCliente' de un cliente en UCRM. * * @param int|string $clientId ID del cliente * @param string $newPassword Nueva contraseña a setear * @return array [success => bool, message => string] */ function updateClientPasswordAttribute($clientId, $newPassword) { $configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create(); $config = $configManager->loadConfig(); $baseUri = $config['ipserver']; $crmAuthToken = $config['apitoken']; // O $config['ucrmApiToken'] si así lo tienes $clientUcrm = new \GuzzleHttp\Client([ 'base_uri' => 'https://' . $baseUri . '/crm/api/v1.0/', 'verify' => false ]); $logger = \Ubnt\UcrmPluginSdk\Service\PluginLogManager::create(); try { // 1. Obtener el cliente actual $response = $clientUcrm->get('clients/' . $clientId, [ 'headers' => [ 'X-Auth-Token' => $crmAuthToken, 'Content-Type' => 'application/json' ] ]); if ($response->getStatusCode() !== 200) { return ['success' => false, 'message' => 'No se pudo obtener el cliente.']; } $clientData = json_decode($response->getBody(), true); // 2. Buscar el atributo personalizado 'passwordAntenaCliente' $found = false; $attributes = []; if (isset($clientData['attributes']) && is_array($clientData['attributes'])) { foreach ($clientData['attributes'] as $attr) { if ($attr['key'] === 'passwordAntenaCliente') { $attr['value'] = $newPassword; $found = true; } $attributes[] = $attr; } } if (!$found) { return ['success' => false, 'message' => 'No se encontró el atributo personalizado passwordAntenaCliente.']; } // 3. Actualizar el cliente completo usando PATCH // Solo enviar el array attributes con customAttributeId y value $logger->appendLog('PATCH endpoint: clients/' . $clientId); $patchBody = [ 'attributes' => [ [ 'customAttributeId' => 17, 'value' => $newPassword ] ] ]; $logger->appendLog('PATCH body: ' . json_encode($patchBody)); try { $patchResponse = $clientUcrm->patch('clients/' . $clientId, [ 'headers' => [ 'X-Auth-Token' => $crmAuthToken, 'Content-Type' => 'application/json' ], 'json' => $patchBody ]); $logger->appendLog('PATCH status: ' . $patchResponse->getStatusCode()); $logger->appendLog('PATCH response: ' . $patchResponse->getBody()); if ($patchResponse->getStatusCode() === 200) { return ['success' => true, 'message' => 'Contraseña actualizada correctamente.']; } else { return ['success' => false, 'message' => 'Error al actualizar el cliente.']; } } catch (Exception $e) { $logger->appendLog('PATCH exception: ' . $e->getMessage()); return ['success' => false, 'message' => 'Excepción: ' . $e->getMessage()]; } } catch (Exception $e) { $logger->appendLog('PATCH attributes exception: ' . $e->getMessage()); return ['success' => false, 'message' => 'Excepción: ' . $e->getMessage()]; } } $entrada = trim($_POST['identificador']); // Validar si es una dirección IP válida if (filter_var($entrada, FILTER_VALIDATE_IP)) { // Es una dirección IP válida $respuestaAPI = getVaultCredentials($entrada); } // Validar si es una dirección MAC válida elseif (preg_match('/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/', $entrada)) { // Es una dirección MAC válida $respuestaAPI = getVaultCredentials($entrada); } // Validar si es un ID numérico menor a 10,000 elseif (ctype_digit($entrada) && intval($entrada) < 10000) { // Es un ID válido $respuestaAPI = getVaultCredentials($entrada); } else { // Entrada no válida $mensajeError = "La entrada no es válida. Por favor, ingresa una dirección IP, una dirección MAC o un ID menor a 10,000."; } // Verificar si la respuesta de la API indica un error if (strpos($respuestaAPI, "Error:") === 0) { $esError = true; } } function setNewPassword($clientId, $newPassword) { // Aquí iría la lógica para actualizar la contraseña del cliente en UCRM // Usando la API de UCRM y el cliente Guzzle // Retornar true si se actualizó correctamente, false en caso contrario global $clientFullName, $IpAddressClientId; $logger = \Ubnt\UcrmPluginSdk\Service\PluginLogManager::create(); $configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create(); $config = $configManager->loadConfig(); $baseUri = $config['ipserver']; $crmAuthToken = $config['apitoken']; $unmsAuthToken = $config['unmsApiToken']; $ucrmBaseUri = 'https://' . $baseUri . '/crm/api/v1.0/'; $clientUcrm = new Client([ 'base_uri' => $ucrmBaseUri, 'verify' => false // Deshabilitar la verificación del certificado SSL ]); try { $responseClient = $clientUcrm->patch('clients/' . $clientId, [ 'headers' => [ 'X-Auth-Token' => $crmAuthToken, 'Content-Type' => 'application/json' ], 'json' => [ 'attributes' => [ [ 'customAttributeId' => 17, // ID del atributo personalizado 'passwordAntenaCliente' 'value' => $newPassword ] ] ] ]); if ($responseClient->getStatusCode() === 200) { $logger->appendLog('Contraseña actualizada correctamente para el cliente: ' . $clientFullName . ' (ID: ' . $IpAddressClientId . ')'); return true; } else { $logger->appendLog('Error al actualizar la contraseña. Código de estado HTTP: ' . $responseClient->getStatusCode()); return false; } } catch (RequestException $e) { $logger->appendLog('Excepción al actualizar la contraseña: ' . $e->getMessage()); return false; } } function getVaultCredentials($dataToSearch): string { global $clientFullName, $IpAddressClientId, $clientIdentifierType; $logger = \Ubnt\UcrmPluginSdk\Service\PluginLogManager::create(); $configManager = \Ubnt\UcrmPluginSdk\Service\PluginConfigManager::create(); $config = $configManager->loadConfig(); $baseUri = $config['ipserver']; $crmAuthToken = $config['apitoken']; $unmsAuthToken = $config['unmsApiToken']; $unmsBaseUri = 'https://' . $baseUri . '/nms/api/v2.1/'; $ucrmBaseUri = 'https://' . $baseUri . '/crm/api/v1.0/'; //$authToken = '7adc9198-50b1-41d0-9bfa-d4946902ed89'; // Crear una instancia del cliente Guzzle $clientUnms = new Client([ 'base_uri' => $unmsBaseUri, 'verify' => false // Deshabilitar la verificación del certificado SSL ]); $clientUcrm = new Client([ 'base_uri' => $ucrmBaseUri, 'verify' => false // Deshabilitar la verificación del certificado SSL ]); //validar si dataToSearch es una dirección IP o una dirección MAC if (filter_var($dataToSearch, FILTER_VALIDATE_IP)) { $clientIdentifierType = 'IP'; // La variable es una dirección IP válida $logger->appendLog('Consulta por dirección IP: ' . $dataToSearch); $IpAddressClientId = filter_var($dataToSearch, FILTER_VALIDATE_IP); try { $responseSitesByIP = $clientUnms->request('GET', 'sites/search?query=' . $dataToSearch . '&count=1&page=1', [ 'headers' => [ 'X-Auth-Token' => $unmsAuthToken ] ]); //Sites por IP if ($responseSitesByIP->getStatusCode() === 200) { $datasSitesByIP = json_decode($responseSitesByIP->getBody(), true); $jsonDevicesBySite = json_encode($datasSitesByIP, JSON_PRETTY_PRINT); //print_r($jsonDevicesBySite . PHP_EOL); //Devices por ID del sitio if (isset($datasSitesByIP[0])) { $siteId = $datasSitesByIP[0]['id']; // print_r('ID DEL SITIO: ' . $siteId . PHP_EOL); // ID del sitio } else { $logger->appendLog('No se encontró ningún sitio para la IP proporcionada: ' . $dataToSearch); return 'Error: No se encontró ningún sitio para la IP proporcionada: ' . $dataToSearch; // Return early if no site is found } } else { //echo "Error en la solicitud. Código de estado HTTP: " . $responseSitesByIP->getStatusCode() . PHP_EOL; $logger->appendLog('Error en la solicitud. Código de estado HTTP: ' . $responseSitesByIP->getStatusCode()); return 'Error: Falla en la solicitud. Código de estado HTTP: ' . $responseSitesByIP->getStatusCode(); // Return early if the request fails } $devicesBySiteId = $clientUnms->request('GET', 'devices?siteId=' . $siteId, [ 'headers' => [ 'X-Auth-Token' => $unmsAuthToken ] ]); //Devices por ID del sitio if ($devicesBySiteId->getStatusCode() === 200) { $dataDevicesBySite = json_decode($devicesBySiteId->getBody(), true); $jsonDevicesBySite = json_encode($dataDevicesBySite, JSON_PRETTY_PRINT); //print_r($jsonDevicesBySite . PHP_EOL); //Devices por ID del sitio $deviceID = null; foreach ($dataDevicesBySite as $device) { if (isset($device['ipAddress'])) { $ipAddress = explode('/', $device['ipAddress'])[0]; // Obtener solo la IP sin la máscara if ($ipAddress === $IpAddressClientId) { $deviceID = $device['identification']['id']; // ID del dispositivo break; // Salir del ciclo si se encuentra la IP } } else { $logger->appendLog('No se encontró la IP del dispositivo en la respuesta de la API.'); return 'Error: No se encontró la IP del dispositivo en la respuesta de la API.'; // Return early if the IP is not found } } if ($deviceID == null) { //echo "No se encontró el dispositivo con la IP proporcionada." . PHP_EOL; $logger->appendLog('No se encontró el dispositivo con la IP proporcionada: ' . $IpAddressClientId); return 'Error: No se encontró el dispositivo con la IP proporcionada: ' . $IpAddressClientId; // Return early if no device is found } } else { // echo "Error en la solicitud. Código de estado HTTP: " . $devicesBySiteId->getStatusCode() . PHP_EOL; $logger->appendLog('Error en la solicitud. Código de estado HTTP: ' . $devicesBySiteId->getStatusCode()); return 'Error: Falla en la solicitud. Código de estado HTTP: ' . $devicesBySiteId->getStatusCode(); // Return early if the request fails } $responsePasswordVault = $clientUnms->request('GET', 'vault/' . $deviceID . '/credentials', [ 'headers' => [ 'X-Auth-Token' => $unmsAuthToken ] ]); if ($responsePasswordVault->getStatusCode() === 200) { $dataPasswordVault = json_decode($responsePasswordVault->getBody(), true); // $jsonPasswordVault = json_encode($dataPasswordVault, JSON_PRETTY_PRINT); //print_r($jsonPasswordVault . PHP_EOL); //Cred if (isset($dataPasswordVault['credentials'][0]['password'])) { //asignar el campo password a la variable dataPasswordVault $dataPasswordVault = $dataPasswordVault['credentials'][0]['password']; } else { // echo "No se encontró la contraseña en la respuesta de la API." . PHP_EOL; $logger->appendLog('No se encontró una contraseña en la bóveda para la antena de este cliente, es altamente probable que conserve una contraseña conocida.'); return "Error: No se encontró una contraseña en la bóveda para la antena de este cliente, es altamente probable que conserve una contraseña conocida."; // Return early if the password is not found } return $dataPasswordVault; } else { // echo "Error en la solicitud. Código de estado HTTP: " . $responsePasswordVault->getStatusCode() . PHP_EOL; $logger->appendLog('Error en la solicitud. Código de estado HTTP: ' . $responsePasswordVault->getStatusCode()); return 'Error: Falla en la solicitud. Código de estado HTTP: ' . $responsePasswordVault->getStatusCode(); // Return early if the request fails } } catch (RequestException $requestException) { // Manejar errores de la solicitud, si hay error 404 entonces responder que no se encontró niguna IP asociada a alguna antena o dispositivo de red if ($requestException->hasResponse()) { $response = $requestException->getResponse(); $statusCode = $response->getStatusCode(); $reason = $response->getReasonPhrase(); // echo "Error: {$statusCode} - {$reason}" . PHP_EOL; // echo $response->getBody(); if ($statusCode == 404) { // echo "No se encontró el cliente con la dirección IP proporcionada." . PHP_EOL; $logger->appendLog('No se encontró el cliente con la dirección IP proporcionada: ' . $IpAddressClientId); return 'Error: No se encontró el cliente con la dirección IP proporcionada: ' . $IpAddressClientId; // Return early if the client is not found } return 'Error: ' . $reason; // Return early if the request fails } else { // echo "Error: " . $requestException->getMessage() . PHP_EOL; $logger->appendLog('Error: ' . $requestException->getMessage()); return 'Error: ' . $requestException->getMessage(); // Return early if the request fails } } } else if (preg_match('/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/', $dataToSearch)) { $clientIdentifierType = 'MAC'; // La variable es una dirección MAC válida $logger->appendLog('Consulta por dirección MAC: ' . $dataToSearch); try { // //para mandarla al endpoint de dispositivos por MAC se necesita convertir la cadena de la direccion mac en un formato como el siguiente ejemplo: para la dirección mac 60:22:32:c8:b2:c3 quedaría como 60%3A22%3A32%3Ac8%3Ab2%3Ac3 // $dataToSearch = str_replace(':', '%3A', $dataToSearch); // $logger->appendLog('Consulta por dirección MAC: ' . $dataToSearch ); $responseDeviceByMAC = $clientUnms->request('GET', 'devices/mac/' . $dataToSearch, [ 'headers' => [ 'X-Auth-Token' => $unmsAuthToken ] ]); if ($responseDeviceByMAC->getStatusCode() === 200) { $dataDeviceByMAC = json_decode($responseDeviceByMAC->getBody(), true); $jsonDeviceByMac = json_encode($dataDeviceByMAC, JSON_PRETTY_PRINT); // print_r($jsonDeviceByMac . PHP_EOL); //Devices por ID del sitio //$logger->appendLog($jsonDeviceByMac.PHP_EOL); //Ejemplo de $responseDeviceByMac en json: {"id":"84c8a581-154c-41db-81d5-a1b1c9ede411","type":"airMax","series":"AC"} //obtener el id del dispositivo y si no existe el id del dispositivo entonces devolver un mensaje de error if (isset($dataDeviceByMAC['id'])) { $deviceId = $dataDeviceByMAC['id']; // print_r('ID DEL DISPOSITIVO: ' . $deviceId . PHP_EOL); // ID del dispositivo } else { // echo "No se encontró el dispositivo con la dirección MAC proporcionada." . PHP_EOL; $logger->appendLog('No se encontró el dispositivo con la dirección MAC proporcionada: ' . $dataToSearch); return 'Error: No se encontró el dispositivo con la dirección MAC proporcionada: ' . $dataToSearch; // Return early if no device is found } } $responsePasswordVault = $clientUnms->request('GET', 'vault/' . $deviceId . '/credentials', [ 'headers' => [ 'X-Auth-Token' => $unmsAuthToken ] ]); if ($responsePasswordVault->getStatusCode() === 200) { $dataPasswordVault = json_decode($responsePasswordVault->getBody(), true); // $jsonPasswordVault = json_encode($dataPasswordVault, JSON_PRETTY_PRINT); //print_r($jsonPasswordVault . PHP_EOL); //Credenciales del dispositivo if (isset($dataPasswordVault['credentials'][0]['password'])) { //asignar el campo password a la variable dataPasswordVault $dataPasswordVault = $dataPasswordVault['credentials'][0]['password']; } else { // echo "No se encontró la contraseña en la respuesta de la API." . PHP_EOL; $logger->appendLog('No se encontró una contraseña en la bóveda para la antena de este cliente, es altamente probable que conserve una contraseña conocida.'); return "Error: No se encontró una contraseña en la bóveda para la antena de este cliente, es altamente probable que conserve una contraseña conocida."; // Return early if the password is not found } return $dataPasswordVault; } else { // echo "Error en la solicitud. Código de estado HTTP: " . $responsePasswordVault->getStatusCode() . PHP_EOL; $logger->appendLog('Error en la solicitud. Código de estado HTTP: ' . $responsePasswordVault->getStatusCode()); return 'Error: Falla en la solicitud. Código de estado HTTP: ' . $responsePasswordVault->getStatusCode(); // Return early if the request fails } } catch (RequestException $requestException) { // Manejar errores de la solicitud, si hay error 404 entonces responder que no se encontró niguna MAC asociada a alguna antena o dispositivo de red if ($requestException->hasResponse()) { $response = $requestException->getResponse(); $statusCode = $response->getStatusCode(); $reason = $response->getReasonPhrase(); // echo "Error: {$statusCode} - {$reason}" . PHP_EOL; // echo $response->getBody(); if ($statusCode == 404) { // echo "No se encontró el cliente con la dirección MAC proporcionada." . PHP_EOL; $logger->appendLog('No se encontró ninguna antena de cliente o dispositivo en la red con la dirección MAC proporcionada: ' . $dataToSearch); return 'Error: No se encontró ninguna antena de cliente o dispositivo en la red con la dirección MAC proporcionada: ' . $dataToSearch; // Return early if the client is not found } return 'Error: ' . $reason; // Return early if the request fails } else { // echo "Error: " . $requestException->getMessage() . PHP_EOL; $logger->appendLog('Error: ' . $requestException->getMessage()); return 'Error: ' . $requestException->getMessage(); // Return early if the request fails } } } else { $clientIdentifierType = 'ID'; // La variable no es una dirección IP válida, se asume que es un ID $IpAddressClientId = filter_var($dataToSearch, FILTER_SANITIZE_NUMBER_INT); //print ('Consulta por ID: ' . $dataToSearch . PHP_EOL); // $logger->appendLog('Consulta por ID' . $dataToSearch); // $logger->appendLog('endpoint que se envía: '.$ucrmBaseUri.'clients/services?clientId=' . $IpAddressClientId); // $logger->appendLog('apiToken que se usa: '.$crmAuthToken); try { //Obtener id del sitio por medio del servicio $responseServices = $clientUcrm->get('clients/services?clientId=' . $IpAddressClientId, [ 'headers' => [ 'X-Auth-Token' => $crmAuthToken, 'Content-Type: application/json' ] ]); //Obtener el nombre del cliente por medio del ID $responseClientName = $clientUcrm->get('clients/' . $IpAddressClientId, [ 'headers' => [ 'X-Auth-Token' => $crmAuthToken, 'Content-Type: application/json' ] ]); //ejemplo de responseClientName en json: {"id":3201,"userIdent":null,"previousIsp":null,"isLead":false,"clientType":1,"companyName":null,"companyRegistrationNumber":null,"companyTaxId":null,"companyWebsite":null,"street1":"CALLE CHIAPAS #31, ZONA CENTRO","street2":null,"city":"Dolores Hidalgo Cuna de la Independencia Nacional","countryId":173,"stateId":null,"zipCode":"37800","fullAddress":"CALLE CHIAPAS #31, ZONA CENTRO, Dolores Hidalgo Cuna de la Independencia Nacional, 37800","invoiceStreet1":null,"invoiceStreet2":null,"invoiceCity":null,"invoiceStateId":null,"invoiceCountryId":null,"invoiceZipCode":null,"invoiceAddressSameAsContact":true,"note":"Soy un teibolero :) programador en SIIP INTERNET","sendInvoiceByPost":null,"invoiceMaturityDays":17,"stopServiceDue":false,"stopServiceDueDays":null,"organizationId":1,"tax1Id":null,"tax2Id":null,"tax3Id":null,"registrationDate":"2024-04-19T00:00:00-0600","leadConvertedAt":null,"companyContactFirstName":null,"companyContactLastName":null,"isActive":false,"firstName":"DANIEL HUMBERTO","lastName":"SOTO VILLEGAS","username":"dhsv.141089@gmail.com","contacts":[{"id":4188,"clientId":3201,"email":"dhsv.141089@gmail.com","phone":"5214181878106","name":null,"isBilling":false,"isContact":false,"types":[{"id":4,"name":"WhatsApp"}]},{"id":5242,"clientId":3201,"email":null,"phone":"5214181148783","name":"WA Bussiness","isBilling":false,"isContact":false,"types":[]}],"attributes":[{"id":21180,"clientId":3201,"customAttributeId":35,"name":"Site","key":"site","value":"0LOCS","clientZoneVisible":true},{"id":18147,"clientId":3201,"customAttributeId":1,"name":"ip","key":"ip","value":"172.16.13.64","clientZoneVisible":false},{"id":19859,"clientId":3201,"customAttributeId":29,"name":"Stripe Customer ID","key":"stripeCustomerId","value":"cus_RKiSN955qKhmch","clientZoneVisible":true},{"id":19860,"clientId":3201,"customAttributeId":30,"name":"Clabe Interbancaria","key":"clabeInterbancaria","value":"124180650741646979","clientZoneVisible":true},{"id":21181,"clientId":3201,"customAttributeId":36,"name":"Antena/Sectorial","key":"antenaSectorial","value":"Sectorial-4b 172.16.13.16/24","clientZoneVisible":true},{"id":27184,"clientId":3201,"customAttributeId":21,"name":"Chat de CallBell","key":"chatDeCallbell","value":"https://dash.callbell.eu/chat/90611886ac204c56a75240f951c53874","clientZoneVisible":false},{"id":28687,"clientId":3201,"customAttributeId":22,"name":"uuid","key":"uuid","value":"2038d2d99ae543f3b56f1ae54f4cc82b","clientZoneVisible":false},{"id":29853,"clientId":3201,"customAttributeId":37,"name":"Password Antena Cliente","key":"passwordAntenaCliente","value":"gYAIEK:Be}SK*01z5+/V","clientZoneVisible":false}],"accountBalance":-300,"accountCredit":0,"accountOutstanding":300,"currencyCode":"MXN","organizationName":"SIIP","bankAccounts":[{"id":2,"accountNumber":"124180650741646979"}],"tags":[{"id":1,"name":"NS EXENTO","colorBackground":"#00a0df","colorText":"#fff"}],"invitationEmailSentDate":null,"avatarColor":"#4caf50","addressGpsLat":21.1564209,"addressGpsLon":-100.9384185,"isArchived":false,"generateProformaInvoices":null,"usesProforma":false,"hasOverdueInvoice":true,"hasOutage":false,"hasSuspendedService":false,"hasServiceWithoutDevices":false,"referral":null,"hasPaymentSubscription":false,"hasAutopayCreditCard":false} $clientName = json_decode($responseClientName->getBody(), true); $clientFullName = $clientName['firstName'] . ' ' . $clientName['lastName']; $logger->appendLog('CLIENTE: ' . $clientFullName . ' (ID: ' . $IpAddressClientId . ')'); } catch (RequestException $requestException) { // Manejar errores de la solicitud if ($requestException->hasResponse()) { $response = $requestException->getResponse(); $statusCode = $response->getStatusCode(); $reason = $response->getReasonPhrase(); //si el statusCode es 404 significa que no se encontró el cliente if ($statusCode == 404) { // echo "No se encontró el cliente con el ID proporcionado." . PHP_EOL; $logger->appendLog('No se encontró el cliente con el ID proporcionado: ' . $IpAddressClientId); return 'Error: No se encontró el cliente con el ID proporcionado: ' . $IpAddressClientId; // Return early if the client is not found } return 'Error: ' . $reason; // Return early if the request fails } else { // echo "Error: " . $requestException->getMessage() . PHP_EOL; $logger->appendLog('Error: ' . $requestException->getMessage()); return 'Error: ' . $requestException->getMessage(); // Return early if the request fails } } if ($responseServices->getStatusCode() === 200) { $dataServices = json_decode($responseServices->getBody(), true); // $jsonServices = json_encode($dataServices, JSON_PRETTY_PRINT); // print_r($jsonServices . PHP_EOL); if (isset($dataServices[0])) { $unmsSiteID = $dataServices[0]['unmsClientSiteId']; // Example: 9c6798f3-0254-4e5b-bc3b-9da82fe16e46 } else { // echo "No se encontraron servicios para el cliente proporcionado." . PHP_EOL; $logger->appendLog('No se encontraron servicios para el cliente proporcionado: ' . $IpAddressClientId); return "Error: No se encontraron servicios para el cliente proporcionado: " . $IpAddressClientId; // Return early if no services are found } } else { // echo "Error en la solicitud. Código de estado HTTP: " . $responseServices->getStatusCode() . PHP_EOL; $logger->appendLog('Error en la solicitud. Código de estado HTTP: ' . $responseServices->getStatusCode()); return "Error: En la solicitud. Código de estado HTTP: " . $responseServices->getStatusCode(); } // $logger->appendLog('ID del sitio obtenido: ' . $unmsSiteID); // $logger->appendLog('endpoint que se envía: '.$unmsBaseUri.'devices?siteId=' . $unmsSiteID); // $logger->appendLog('apiToken que se usa: '.$crmAuthToken); $responseDevicesBySite = $clientUnms->request('GET', 'devices?siteId=' . $unmsSiteID, [ 'headers' => [ 'X-Auth-Token' => $unmsAuthToken ] ]); if ($responseDevicesBySite->getStatusCode() === 200) { $dataDevicesBySite = json_decode($responseDevicesBySite->getBody(), true); $jsonDevicesBySite = json_encode($dataDevicesBySite, JSON_PRETTY_PRINT); //print_r($jsonDevicesBySite . PHP_EOL); //Devices por ID del sitio //id del device al que está conectado el cliente if (isset($dataDevicesBySite[0])) { $idClientDevice = $dataDevicesBySite[0]['identification']['id']; $deviceID = $dataDevicesBySite[0]['attributes']['apDevice']['id']; } else { // echo "No se encontraron dispositivos para el sitio proporcionado." . PHP_EOL; $logger->appendLog('No se encontraron dispositivos para el sitio proporcionado: ' . $unmsSiteID); return "Error: No se encontraron dispositivos para el sitio proporcionado."; // Return early if no devices are found } } else { // echo "Error en la solicitud. Código de estado HTTP: " . $responseDevicesBySite->getStatusCode() . PHP_EOL; $logger->appendLog('Error en la solicitud. Código de estado HTTP: ' . $responseDevicesBySite->getStatusCode()); return "Error: Falla en la solicitud. Código de estado HTTP: " . $responseDevicesBySite->getStatusCode(); } // $logger->appendLog('ID del device al que está conectado el cliente: ' . $deviceID); // $logger->appendLog('endpoint que se envía: '.$unmsBaseUri.'devices/' . $deviceID); // $logger->appendLog('apiToken que se usa: '.$unmsAuthToken); $responseDevicesBySite = $clientUnms->request('GET', 'devices/' . $deviceID, [ 'headers' => [ 'X-Auth-Token' => $unmsAuthToken ] ]); if ($responseDevicesBySite->getStatusCode() === 200) { $dataDevices = json_decode($responseDevicesBySite->getBody(), true); $jsonDevices = json_encode($dataDevices, JSON_PRETTY_PRINT); //print_r($jsonDevices . PHP_EOL); // $logger->appendLog('ID del device al que está conectado el cliente: ' . $idDevice); // $logger->appendLog('endpoint que se envía: '.$unmsBaseUri.'vault/' . $idDevice . '/credentials'); // $logger->appendLog('apiToken que se usa: '.$unmsAuthToken); //print_r('ID del device al que está conectado el cliente: ' . $idDevice . PHP_EOL); $responsePasswordVault = $clientUnms->request('GET', 'vault/' . $idClientDevice . '/credentials', [ 'headers' => [ 'X-Auth-Token' => $unmsAuthToken ] ]); if ($responsePasswordVault->getStatusCode() === 200) { $dataPasswordVault = json_decode($responsePasswordVault->getBody(), true); $jsonPasswordVault = json_encode($dataPasswordVault, JSON_PRETTY_PRINT); // $logger->appendLog($jsonPasswordVault); //Credenciales del dispositivo //ejemplo de $responsePasswordVault en json: {"credentials":[{"username":"ubnt","readOnly":false,"password":"gYAIEK:Be}SK*01z5+/V","createdAt":"2025-03-27T23:29:54.948Z"}],"isPassphraseMissing":false} //verificar si existe la contraseña en la respuesta de la API if (isset($dataPasswordVault['credentials'][0]['password'])) { //asignar el campo password a la variable dataPasswordVault $dataPasswordVault = $dataPasswordVault['credentials'][0]['password']; } else { // echo "No se encontró la contraseña en la respuesta de la API." . PHP_EOL; $logger->appendLog('Id device: ' . $idClientDevice); $logger->appendLog('No se encontró una contraseña en la bóveda para la antena de este cliente, es altamente probable que conserve una contraseña conocida.'); return "Error: No se encontró una contraseña en la bóveda para la antena de este cliente, es altamente probable que conserve una contraseña conocida."; // Return early if the password is not found } return $dataPasswordVault; } else { // echo "Error en la solicitud. Código de estado HTTP: " . $responseDevicesBySite->getStatusCode() . PHP_EOL; $logger->appendLog('Error en la solicitud. Código de estado HTTP: ' . $responsePasswordVault->getStatusCode()); return 'Error: Falla en la solicitud. Código de estado HTTP: ' . $responsePasswordVault->getStatusCode(); // Return early if the request fails } } else { // echo "Error en la solicitud. Código de estado HTTP: " . $responseDevicesBySite->getStatusCode() . PHP_EOL; $logger->appendLog('Error en la solicitud. Código de estado HTTP: ' . $responseDevicesBySite->getStatusCode()); return 'Error: Falla en la solicitud. Código de estado HTTP: ' . $responseDevicesBySite->getStatusCode(); // Return early if the request fails } } } global $clientFullName, $IpAddressClientId; // Variables globales para usar en la función getVaultCredentials /** * Genera una contraseña aleatoria y fuerte (CSPRNG). * * - Garantiza al menos 1 minúscula, 1 mayúscula, 1 dígito y 1 símbolo. * - Usa random_int() / random_bytes() (CSPRNG). * - Evita sesgos al seleccionar y mezcla la contraseña con Fisher-Yates. * * @param int $length Longitud deseada (mínimo 8). Default 20. * @param bool $avoid_ambiguous Si true evita caracteres ambiguos como l, I, 0, O. * @return string Contraseña generada. * @throws InvalidArgumentException Si $length < 8. */ function generate_strong_password(int $length = 20, bool $avoid_ambiguous = true): string { if ($length < 8) { throw new InvalidArgumentException('La longitud mínima recomendada es 8 caracteres.'); } // Conjuntos de caracteres $lower = 'abcdefghijklmnopqrstuvwxyz'; $upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; $digits = '0123456789'; // Conjunto de símbolos seguros; puedes ampliarlo si lo deseas $symbols = '!@#$%&*()-_=+[]{};:,.<>?'; if ($avoid_ambiguous) { // Eliminar caracteres ambiguos $amb = ['l', 'I', '1', '0', 'O']; $lower = str_replace($amb, '', $lower); $upper = str_replace($amb, '', $upper); $digits = str_replace($amb, '', $digits); // los símbolos raramente confunden, los mantenemos } // Asegurar al menos uno de cada tipo $required = []; $required[] = $lower[random_int(0, strlen($lower) - 1)]; $required[] = $upper[random_int(0, strlen($upper) - 1)]; $required[] = $digits[random_int(0, strlen($digits) - 1)]; $required[] = $symbols[random_int(0, strlen($symbols) - 1)]; // Relleno con una mezcla de todos los conjuntos $all = $lower . $upper . $digits . $symbols; $remaining = $length - count($required); $pwChars = $required; for ($i = 0; $i < $remaining; $i++) { $pwChars[] = $all[random_int(0, strlen($all) - 1)]; } // Mezclar usando Fisher-Yates con random_int (sin sesgo) $n = count($pwChars); for ($i = $n - 1; $i > 0; $i--) { $j = random_int(0, $i); $tmp = $pwChars[$i]; $pwChars[$i] = $pwChars[$j]; $pwChars[$j] = $tmp; } return implode('', $pwChars); } ?>