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
This commit is contained in:
Yuri Karamian
2026-06-22 01:13:55 +02:00
parent 815d1a442b
commit 26bdabc534
3 changed files with 71 additions and 15 deletions
+6
View File
@@ -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
@@ -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 <support@arkhost.com>
* @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 <addr>/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,7 +1576,30 @@ function ArkHostHetznerVPS_AdminLink(array $params) {
if (isset($serverInfo['server'])) {
$server = $serverInfo['server'];
return '<i class="fa fa-server"></i> Status: ' . $server['status'] . '<br><i class="fa fa-network-wired"></i> 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 '<i class="fa fa-server"></i> Status: ' . $server['status'] . '<br><i class="fa fa-network-wired"></i> IP: ' . ($primaryIp !== '' ? $primaryIp : 'N/A');
}
return 'Server ID: ' . $vpsId;
@@ -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
$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 {
// Password has expired (timestamp exists and is older than 72 hours)
$serverInfo['install_root'] = '';
// 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' => '']);
}
} else {
$serverInfo['install_root'] = '';
}
+1 -1
View File
@@ -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 <support@arkhost.com>
* @link https://arkhost.com