diff --git a/services/nginx/app/routes/departmentSelfserveVehicleConditionsRoute.php b/services/nginx/app/routes/departmentSelfserveVehicleConditionsRoute.php index d6efafe6..4c1e4935 100644 --- a/services/nginx/app/routes/departmentSelfserveVehicleConditionsRoute.php +++ b/services/nginx/app/routes/departmentSelfserveVehicleConditionsRoute.php @@ -131,7 +131,7 @@ class departmentSelfserveVehicleConditionsRoute $lane_id = (int)self::getParameter('lane_id'); $reg = selfserve::standardize_registration((string)self::getParameter('reg')); - $lane = $this->assertLaneAccess($user, $lane_id, $has_global); + $lane = $this->assertLaneAccess($user, $lane_id); $customer_number = null; if (!$has_global && $has_own) { $customer_number = $this->requireAuthenticatedCustomerNumber($user, 'list_department_selfserve_vehicle_conditions'); @@ -193,7 +193,7 @@ class departmentSelfserveVehicleConditionsRoute $lane_id = (int)self::getParameter('lane_id'); $reg = selfserve::standardize_registration((string)self::getParameter('reg')); - $this->assertLaneAccess($user, $lane_id, $has_global); + $this->assertLaneAccess($user, $lane_id); $customer_number = null; if (!$has_global && $has_own) { $customer_number = $this->requireAuthenticatedCustomerNumber($user, 'list_department_selfserve_vehicle_conditions'); @@ -527,7 +527,7 @@ class departmentSelfserveVehicleConditionsRoute return $default; } - private function assertLaneAccess(object $user, int $laneId, bool $hasGlobalPermission): department_lanes_o + private function assertLaneAccess(object $user, int $laneId): department_lanes_o { global $response; @@ -536,11 +536,14 @@ class departmentSelfserveVehicleConditionsRoute $response->error('Department lane not found', 404); } - if ($hasGlobalPermission) { - $authorized_department_ids = $user->getGroup()->getDepartments(); - if (!in_array((int)$lane->department->value(), $authorized_department_ids, true)) { - $this->forbidDepartmentAccess((int)$lane->department->value()); - } + $lane_department_id = (int)$lane->department->value(); + $authorized_department_ids = array_values(array_filter( + array_map('intval', (array)$user->getGroup()->getDepartments()), + static fn(int $department_id): bool => $department_id > 0 + )); + + if (!in_array($lane_department_id, $authorized_department_ids, true)) { + $this->forbidDepartmentAccess($lane_department_id); } return $lane; diff --git a/services/nginx/app/tests/Unit/Selfserve/SelfserveEligibilityLaneAccessTest.php b/services/nginx/app/tests/Unit/Selfserve/SelfserveEligibilityLaneAccessTest.php new file mode 100644 index 00000000..b9943bc8 --- /dev/null +++ b/services/nginx/app/tests/Unit/Selfserve/SelfserveEligibilityLaneAccessTest.php @@ -0,0 +1,58 @@ +{$method}('{$path}'"); + if ($start === false) { + throw new RuntimeException("Route block not found: {$method} {$path}"); + } + + $nextComment = strpos($route, "\n /**", $start + 1); + if ($nextComment === false) { + return substr($route, $start); + } + + return substr($route, $start, $nextComment - $start); +} + +function selfserve_eligibility_method_block(string $route, string $signature): string +{ + $start = strpos($route, $signature); + if ($start === false) { + throw new RuntimeException("Method not found: {$signature}"); + } + + $nextMethod = strpos($route, "\n private function ", $start + strlen($signature)); + if ($nextMethod === false) { + return substr($route, $start); + } + + return substr($route, $start, $nextMethod - $start); +} + +it('authorizes customer eligibility preview lanes before returning task attachments', function (): void { + $route = selfserve_eligibility_route_source(); + $allowedBlock = selfserve_eligibility_route_block($route, 'get', '/department/selfserve/vehicle/allowed'); + $assertBlock = selfserve_eligibility_method_block($route, 'private function assertLaneAccess(object $user, int $laneId): department_lanes_o'); + + expect($allowedBlock)->toContain('$lane = $this->assertLaneAccess($user, $lane_id);') + ->and($allowedBlock)->toContain('previewVehicleEligibility($lane_id, $reg, $customer_number, $vehicle_type_id)') + ->and(strpos($allowedBlock, '$lane = $this->assertLaneAccess($user, $lane_id);')) + ->toBeLessThan(strpos($allowedBlock, 'previewVehicleEligibility($lane_id, $reg, $customer_number, $vehicle_type_id)')); + + expect($assertBlock)->toContain('$authorized_department_ids = array_values(array_filter(') + ->and($assertBlock)->toContain('array_map(\'intval\', (array)$user->getGroup()->getDepartments())') + ->and($assertBlock)->toContain('if (!in_array($lane_department_id, $authorized_department_ids, true))') + ->and($assertBlock)->toContain('$this->forbidDepartmentAccess($lane_department_id);') + ->and($assertBlock)->not->toContain('if ($hasGlobalPermission)'); +});