Stop exposing relay local IPs by default

This commit is contained in:
Jeppe B
2026-06-01 23:43:53 +02:00
parent e3b38519fb
commit b25ce9cb11
4 changed files with 61 additions and 13 deletions
@@ -33,7 +33,7 @@ class shelly_relay_inventory
* @return array<int,array<string,mixed>>
* @throws Exception
*/
public function listRelayOptions(): array
public function listRelayOptions(bool $include_sensitive_network_details = false): array
{
$devices_status = $this->fetchOwnedDevicesStatus();
$device_catalog = $this->fetchOwnedDeviceCatalog();
@@ -49,7 +49,8 @@ class shelly_relay_inventory
$option = $this->buildRelayOption(
$normalized_device,
is_array($catalog_entry) ? $catalog_entry : null
is_array($catalog_entry) ? $catalog_entry : null,
$include_sensitive_network_details
);
if ($option === null) {
continue;
@@ -160,7 +161,11 @@ class shelly_relay_inventory
* @param array<string,mixed> $device
* @return array<string,mixed>|null
*/
private function buildRelayOption(array $device, ?array $catalog_entry = null): ?array
private function buildRelayOption(
array $device,
?array $catalog_entry = null,
bool $include_sensitive_network_details = false
): ?array
{
if ($device === [] || !$this->isRelayCapableDevice($device)) {
return null;
@@ -203,9 +208,8 @@ class shelly_relay_inventory
$online = $this->normalizeBoolean($catalog_entry['cloud_online'] ?? null);
}
$status_color = $this->extractStatusColor($online);
$local_ip = $this->extractLocalIp($device, $catalog_entry);
return [
$option = [
'id' => $device_id,
'name' => $this->buildRelayLabel(
$device_type,
@@ -223,10 +227,15 @@ class shelly_relay_inventory
'device_generation' => $device_generation,
'control_type' => $control_type,
'control_name' => $control_name !== '' ? $control_name : null,
'local_ip' => $local_ip,
'status_color' => $status_color,
'online' => $online,
];
if ($include_sensitive_network_details) {
$option['local_ip'] = $this->extractLocalIp($device, $catalog_entry);
}
return $option;
}
/**
@@ -3426,7 +3426,7 @@ BASH;
}
try {
$this->shellyRelayOptionsCache = (new shelly_relay_inventory())->listRelayOptions();
$this->shellyRelayOptionsCache = (new shelly_relay_inventory())->listRelayOptions(true);
} catch (\Throwable) {
$this->shellyRelayOptionsCache = [];
}
@@ -40,7 +40,7 @@ it('keeps relay dispatch and discovery queueing on the edge gateway manager', fu
expect($managerSource)->toContain('private function backfillRelayBindingLocalIpFromInventory');
expect($managerSource)->toContain('$bindingObject->local_ip->set($localIp);');
expect($managerSource)->toContain("'local_ip' => \$localIp");
expect($managerSource)->toContain('(new shelly_relay_inventory())->listRelayOptions()');
expect($managerSource)->toContain('(new shelly_relay_inventory())->listRelayOptions(true)');
expect($managerSource)->toContain('public function buildUpdateOperationRequest');
expect($managerSource)->toContain('public function rotateGatewayCredentials');
expect($operationServiceSource)->toContain('public function queueOperation');
@@ -106,7 +106,6 @@ it('normalizes owned Shelly devices into relay select options', function (): voi
'device_generation' => 2,
'control_type' => 'Switch',
'control_name' => 'Entrance Relay',
'local_ip' => '10.32.0.11',
'status_color' => 'Green',
'online' => true,
],
@@ -122,7 +121,6 @@ it('normalizes owned Shelly devices into relay select options', function (): voi
'device_generation' => 2,
'control_type' => 'Relay',
'control_name' => 'Program Picker',
'local_ip' => '10.32.0.12',
'status_color' => 'Red',
'online' => false,
],
@@ -138,7 +136,6 @@ it('normalizes owned Shelly devices into relay select options', function (): voi
'device_generation' => 1,
'control_type' => 'Relay',
'control_name' => null,
'local_ip' => null,
'status_color' => 'Red',
'online' => false,
],
@@ -194,7 +191,6 @@ it('falls back to local device and control names when Shelly cloud list metadata
'device_generation' => 2,
'control_type' => 'Switch',
'control_name' => 'Entrance Relay',
'local_ip' => '10.32.0.21',
'status_color' => 'Green',
'online' => true,
],
@@ -257,12 +253,55 @@ it('keeps Shelly 1 Mini Gen3 type, model, and generation aligned with Shelly met
'device_generation' => 3,
'control_type' => 'Switch',
'control_name' => null,
'local_ip' => '192.168.1.2',
'status_color' => 'Green',
'online' => true,
]]);
});
it('only includes local IP addresses for internal relay option lookups', function (): void {
$inventory = (new shelly_relay_inventory())
->setInventoryFetcher(static function (): array {
return [
'isok' => true,
'data' => [
'devices_status' => [
'device-key-1' => [
'_dev_info' => [
'id' => 'shelly-plus-01',
'code' => 'SPSW-001PE16EU',
'model' => 'Shelly Plus 1PM',
'online' => 1,
],
'wifi_sta' => [
'ip' => '10.32.0.11',
],
'status' => [
'switch:0' => [
'output' => false,
],
],
],
],
],
];
})
->setDeviceListFetcher(static function (): array {
return [
'isok' => true,
'data' => [
'devices' => [],
],
];
});
$publicOptions = $inventory->listRelayOptions();
$internalOptions = $inventory->listRelayOptions(true);
expect($publicOptions[0])->not->toHaveKey('local_ip');
expect($internalOptions[0])->toHaveKey('local_ip');
expect($internalOptions[0]['local_ip'])->toBe('10.32.0.11');
});
it('fails fast when Shelly inventory does not include owned devices status', function (): void {
$inventory = (new shelly_relay_inventory())->setInventoryFetcher(static function (): array {
return [