From 26bdabc534de38267af2b151de384f6afbcfe034 Mon Sep 17 00:00:00 2001 From: Yuri Karamian Date: Mon, 22 Jun 2026 01:13:55 +0200 Subject: [PATCH] v1.2.4: fix IP/username display and 72h password removal - Store IP on the service at provisioning + backfill existing services - Set service username to root to match the VPS login - Actually delete the install password after the 72h window (was still visible via the eye icon, including legacy services without a timestamp) Fixes #16 --- README.md | 6 ++ .../ArkHostHetznerVPS/ArkHostHetznerVPS.php | 78 +++++++++++++++---- modules/servers/ArkHostHetznerVPS/hooks.php | 2 +- 3 files changed, 71 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index f9cee51..5c6ab24 100644 --- a/README.md +++ b/README.md @@ -340,6 +340,12 @@ Check out our other WHMCS modules at [arkhost.com/whmcs-modules.php](https://ar ## Changelog +### v1.2.4 +**Fixed:** +- IP address now stored on the service at provisioning (and backfilled for existing services) so it displays in WHMCS instead of showing blank +- Service username now set to `root` to match the actual VPS login +- Install password now actually removed after the 72-hour window (was staying visible via the eye icon, including for older services that predated expiry tracking) + ### v1.2.3 **Added:** - VNC console key combination bar with Ctrl+Alt+Del, modifier keys (Shift, Alt, Ctrl), Tab, Enter, Del, Backspace, Esc, Shift+Up, and Fullscreen toggle diff --git a/modules/servers/ArkHostHetznerVPS/ArkHostHetznerVPS.php b/modules/servers/ArkHostHetznerVPS/ArkHostHetznerVPS.php index b9eacc3..cbb977f 100644 --- a/modules/servers/ArkHostHetznerVPS/ArkHostHetznerVPS.php +++ b/modules/servers/ArkHostHetznerVPS/ArkHostHetznerVPS.php @@ -3,7 +3,7 @@ * WHMCS Server Module - Hetzner VPS * * @package WHMCS - * @version 1.2.3 + * @version 1.2.4 * @copyright Copyright (c) ArkHost 2025 * @author ArkHost * @link https://arkhost.com @@ -1176,6 +1176,23 @@ function ArkHostHetznerVPS_CreateAccount(array $params) { 'ArkHostHetznerVPS|VPS ID' => $create['server']['id'], ]); + // Store the primary IP address and login username so they display in WHMCS. + // Without this, the admin service page shows a blank Dedicated IP and the + // auto-generated order username instead of the real VPS login ("root"). + $primaryIp = ''; + if (!empty($create['server']['public_net']['ipv4']['ip'])) { + $primaryIp = $create['server']['public_net']['ipv4']['ip']; + } elseif (!empty($create['server']['public_net']['ipv6']['ip'])) { + // IPv6-only servers report the network as /64; strip the prefix length. + $primaryIp = explode('/', $create['server']['public_net']['ipv6']['ip'])[0]; + } + + $hostingUpdate = array('username' => 'root'); + if ($primaryIp !== '') { + $hostingUpdate['dedicatedip'] = $primaryIp; + } + Capsule::table('tblhosting')->where('id', $params['serviceid'])->update($hostingUpdate); + // Store the root password if provided if (isset($create['root_password'])) { Capsule::table('tblhosting')->where('id', $params['serviceid'])->update([ @@ -1559,9 +1576,32 @@ function ArkHostHetznerVPS_AdminLink(array $params) { if (isset($serverInfo['server'])) { $server = $serverInfo['server']; - return ' Status: ' . $server['status'] . '
IP: ' . $server['public_net']['ipv4']['ip']; + + // Self-heal: backfill IP/username for services created before this was + // stored at provisioning time (and keep the IP current after rebuilds). + $primaryIp = ''; + if (!empty($server['public_net']['ipv4']['ip'])) { + $primaryIp = $server['public_net']['ipv4']['ip']; + } elseif (!empty($server['public_net']['ipv6']['ip'])) { + $primaryIp = explode('/', $server['public_net']['ipv6']['ip'])[0]; + } + + if (!empty($params['serviceid'])) { + $hostingUpdate = array(); + if ($primaryIp !== '' && ($params['dedicatedip'] ?? '') !== $primaryIp) { + $hostingUpdate['dedicatedip'] = $primaryIp; + } + if (($params['username'] ?? '') !== 'root') { + $hostingUpdate['username'] = 'root'; + } + if (!empty($hostingUpdate)) { + Capsule::table('tblhosting')->where('id', $params['serviceid'])->update($hostingUpdate); + } + } + + return ' Status: ' . $server['status'] . '
IP: ' . ($primaryIp !== '' ? $primaryIp : 'N/A'); } - + return 'Server ID: ' . $vpsId; } catch (Exception $err) { ArkHostHetznerVPS_Error(__FUNCTION__, $params, $err); @@ -2466,18 +2506,28 @@ function ArkHostHetznerVPS_ClientArea(array $params) { $currentTime = time(); $expirationPeriod = 72 * 3600; // 72 hours in seconds - if (!empty($params['password']) && $params['password'] !== 'managed-via-api') { - // If no timestamp exists, show the password (backward compatibility or initial setup) - // If timestamp exists, check if it's within the 72-hour window - if (!$passwordSetTime || ($currentTime - $passwordSetTime) < $expirationPeriod) { - // Password is still valid - WHMCS already decrypts it for us in $params - // No need to call decrypt() as $params['password'] is already plain text - $serverInfo['install_root'] = $params['password']; - } else { - // Password has expired (timestamp exists and is older than 72 hours) - $serverInfo['install_root'] = ''; - } + $hasPassword = !empty($params['password']) && $params['password'] !== 'managed-via-api'; + + // Backfill the timestamp for services created before expiry tracking existed. + // Without this, a missing timestamp meant the password was shown forever. + // The service registration date is the best estimate of when it was set. + if ($hasPassword && !$passwordSetTime) { + $regdate = Capsule::table('tblhosting')->where('id', $params['serviceid'])->value('regdate'); + $passwordSetTime = ($regdate && $regdate !== '0000-00-00') ? strtotime($regdate) : $currentTime; + $params['model']->serviceProperties->save([ + 'ArkHostHetznerVPS|Password Set Time' => $passwordSetTime + ]); + } + + if ($hasPassword && ($currentTime - $passwordSetTime) < $expirationPeriod) { + // Password is still within the 72-hour window - WHMCS already decrypts it for us + $serverInfo['install_root'] = $params['password']; } else { + // 72-hour window has elapsed: actually remove the install password from our + // systems so the stored copy matches what the client area promises. + if ($hasPassword) { + Capsule::table('tblhosting')->where('id', $params['serviceid'])->update(['password' => '']); + } $serverInfo['install_root'] = ''; } diff --git a/modules/servers/ArkHostHetznerVPS/hooks.php b/modules/servers/ArkHostHetznerVPS/hooks.php index 740d39c..11f9a33 100644 --- a/modules/servers/ArkHostHetznerVPS/hooks.php +++ b/modules/servers/ArkHostHetznerVPS/hooks.php @@ -3,7 +3,7 @@ * WHMCS Server Module - Hetzner VPS Hooks * * @package WHMCS - * @version 1.2.3 + * @version 1.2.4 * @copyright Copyright (c) ArkHost 2025 * @author ArkHost * @link https://arkhost.com