Merge pull request #263 from copenhagentruckwash/fix-machine-relay-set-endpoint-vulnerability

Guard machine relay set status
This commit is contained in:
Jeppe B
2026-06-02 00:21:49 +02:00
committed by GitHub
2 changed files with 13 additions and 2 deletions
@@ -107,14 +107,16 @@ trait selfserve_lane_relay_controller_t
} }
/** /**
* Set MACHINE relay status directly. * Set MACHINE relay status using the same guards as manual relay controls.
* @param bool $on true to turn on, false to turn off * @param bool $on true to turn on, false to turn off
* @return bool * @return bool
* @throws \Exception * @throws \Exception
*/ */
public function setMachineRelayStatus(bool $on): bool public function setMachineRelayStatus(bool $on): bool
{ {
return $this->setRelayStatus(selfserve_lane_relay::MACHINE, $on); return $on
? $this->turnOnRelay(selfserve_lane_relay::MACHINE)
: $this->turnOffRelay(selfserve_lane_relay::MACHINE);
} }
/** /**
@@ -621,6 +621,14 @@ it('is a safe no-op when MACHINE relay is not configured', function (): void {
expect($harness->getShellyCallCount('/v2/devices/api/set/switch'))->toBe(0); expect($harness->getShellyCallCount('/v2/devices/api/set/switch'))->toBe(0);
}); });
it('blocks setMachineRelayStatus from enabling MACHINE when MACHINE is not allowed', function (): void {
$harness = selfserve_lane_shelly_test_harness();
expect(fn() => $harness->setMachineRelayStatus(true))
->toThrow(\Exception::class, 'MACHINE relay is not allowed to be enabled at this time');
expect($harness->getShellyCallCount('/v2/devices/api/set/switch'))->toBe(0);
});
it('uses local demo responses and skips Shelly cloud calls for demo relay ids', function (): void { it('uses local demo responses and skips Shelly cloud calls for demo relay ids', function (): void {
$harness = selfserve_lane_shelly_test_harness(); $harness = selfserve_lane_shelly_test_harness();
$harness->department_lane = new SelfserveDepartmentLaneRelayFake( $harness->department_lane = new SelfserveDepartmentLaneRelayFake(
@@ -628,6 +636,7 @@ it('uses local demo responses and skips Shelly cloud calls for demo relay ids',
programPickerRelayId: 'demo-program', programPickerRelayId: 'demo-program',
cleanerRelayId: 'demo-cleaner' cleanerRelayId: 'demo-cleaner'
); );
$harness->setLaneCache($harness->id, $harness::CACHE_SELFSERVE_LANE_KEY_ALLOWED_SERVICES, ['MACHINE']);
$result = $harness->setMachineRelayStatus(true); $result = $harness->setMachineRelayStatus(true);
$status = $harness->getMachineRelayStatus(); $status = $harness->getMachineRelayStatus();