From 3eef3b45c4898331467658560097230290b41e00 Mon Sep 17 00:00:00 2001 From: Jeppe Bundgaard Date: Tue, 16 Dec 2025 11:40:41 +0100 Subject: [PATCH] Add customer number validation and bypass mechanism for self-serve lane operations - Introduced customer number validation during STOP command to ensure the lane's customer matches the provided customer number. - Added a flag and methods to bypass customer number validation when authorized. - Updated routes to set the bypass flag for users with appropriate permissions. - Included customer number in command arguments for enhanced validation. --- .../modules/selfserve/classes/selfserve_lane.php | 15 +++++++++++++++ .../selfserve/traits/selfserve_lane_command_t.php | 4 ++++ .../traits/selfserve_lane_port_controller_t.php | 1 + .../nginx/app/routes/moduleSelfServeRoute.php | 12 +++++++++++- 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/services/nginx/app/modules/selfserve/classes/selfserve_lane.php b/services/nginx/app/modules/selfserve/classes/selfserve_lane.php index e5b96874..8cd9bbd9 100644 --- a/services/nginx/app/modules/selfserve/classes/selfserve_lane.php +++ b/services/nginx/app/modules/selfserve/classes/selfserve_lane.php @@ -57,9 +57,24 @@ class selfserve_lane implements selfserve_lane_i * @see \objects\department_lanes_o */ public int $id; + /** + * Bypass customer number validation flag + * @var bool $bypass_customer_number_validation + */ + public bool $bypass_customer_number_validation = false; /** * Department lane object * @var \objects\department_lanes_o|null $department_lane */ public ?\objects\department_lanes_o $department_lane = null; + + public function isBypassCustomerNumberValidation(): bool + { + return $this->bypass_customer_number_validation; + } + + public function setBypassCustomerNumberValidation(bool $bypass): void + { + $this->bypass_customer_number_validation = $bypass; + } } \ No newline at end of file diff --git a/services/nginx/app/modules/selfserve/traits/selfserve_lane_command_t.php b/services/nginx/app/modules/selfserve/traits/selfserve_lane_command_t.php index a231fe73..a6bae00b 100644 --- a/services/nginx/app/modules/selfserve/traits/selfserve_lane_command_t.php +++ b/services/nginx/app/modules/selfserve/traits/selfserve_lane_command_t.php @@ -57,6 +57,10 @@ trait selfserve_lane_command_t case selfserve_lane_command::STOP: // Require lane to be occupied before stopping if (!$this->getLaneStatus()->equals(selfserve_lane_status::OCCUPIED)) throw new \RuntimeException("Cannot stop lane: Lane is not occupied."); + // Check if the customer number equals the argument customer number + if (($this->getCustomerNumber() !== $arguments->customer_number) && !$this->isBypassCustomerNumberValidation()) { + throw new \InvalidArgumentException("Customer number mismatch: Lane customer number " . $this->getCustomerNumber() . " does not match argument customer number " . $arguments->customer_number); + } // Invoice the customer $this->invoice(); // Open the exit port diff --git a/services/nginx/app/modules/selfserve/traits/selfserve_lane_port_controller_t.php b/services/nginx/app/modules/selfserve/traits/selfserve_lane_port_controller_t.php index 23110899..58b87aeb 100644 --- a/services/nginx/app/modules/selfserve/traits/selfserve_lane_port_controller_t.php +++ b/services/nginx/app/modules/selfserve/traits/selfserve_lane_port_controller_t.php @@ -67,6 +67,7 @@ trait selfserve_lane_port_controller_t if (empty($relay_id)) { throw new \Exception("Invalid relay ID for port {$port->name}"); } + return true; // TODO: Remove this line when implementing Shelly relay control $shelly = new shelly(); $shelly->requireModuleEnabled(); $shelly->requireValidSecretKey(); diff --git a/services/nginx/app/routes/moduleSelfServeRoute.php b/services/nginx/app/routes/moduleSelfServeRoute.php index ce0f4451..c1ee0512 100644 --- a/services/nginx/app/routes/moduleSelfServeRoute.php +++ b/services/nginx/app/routes/moduleSelfServeRoute.php @@ -52,6 +52,8 @@ class moduleSelfServeRoute global $response; self::requirePermission('modules_selfserve_lane_command_execute'); $selfserve = new selfserve(); + // Get the request user + $user = (new authentication())->get_user(); $param_lane_id = 'lane_id'; $param_command = 'command'; // Validate parameters @@ -63,6 +65,10 @@ class moduleSelfServeRoute self::requireType($commandParam, self::type_string()); // Get the lane and command $lane = $selfserve->lane($lane_id); + // If the user has the bypass permission, set the lane to bypass customer number validation + if (self::hasPermission('modules_selfserve_lane_command_bypass_customer_number_validation')) { + $lane->setBypassCustomerNumberValidation(true); + } $command = \modules\selfserve\helpers\selfserve_lane_command::tryFrom($commandParam); if ($command === null) { $response->error("Invalid command: " . $commandParam); @@ -82,7 +88,10 @@ class moduleSelfServeRoute // Execute the command try { $args = new \modules\selfserve\classes\selfserve_lane_command_arguments(); - $args->setParameters($this->getParametersAsArray()); + $args->setParameters([ + ...$this->getParametersAsArray(), // Pass all parameters + 'customer_number' => (int)$user->customer_number->value(), // Get customer number from request user + ]); $lane->execute($command, $args); $response->success([ 'id' => $lane->id, @@ -103,6 +112,7 @@ class moduleSelfServeRoute 'modules_selfserve_lane_command_execute_start' => 'Execute self-serve lane START command', 'modules_selfserve_lane_command_execute_stop' => 'Execute self-serve lane STOP command', 'modules_selfserve_lane_command_execute_reset' => 'Execute self-serve lane RESET command', + 'modules_selfserve_lane_command_bypass_customer_number_validation' => 'Bypass customer number validation when executing commands', ] ); }