diff --git a/services/nginx/app/classes/limited_backoffice_service.php b/services/nginx/app/classes/limited_backoffice_service.php index 416d3bac..90072899 100644 --- a/services/nginx/app/classes/limited_backoffice_service.php +++ b/services/nginx/app/classes/limited_backoffice_service.php @@ -29,6 +29,21 @@ class limited_backoffice_service self::PERMISSION_PUBLIC_EMPLOYEE_DATA, ]; + /** + * Permissions that are always granted to managed employees when present in a role preset, + * regardless of whether the creating manager holds those permissions themselves. + * + * @var array + */ + private const ROLE_UNCONDITIONAL_PERMISSIONS = [ + 'list_departments', + 'list_department_daily_reports', + 'list_notifications', + 'list_own_notifications', + 'statistics_orders_new', + 'statistics_bookings_new', + ]; + /** * @var array}> */ @@ -1638,6 +1653,11 @@ class limited_backoffice_service continue; } + if (in_array($permission, self::ROLE_UNCONDITIONAL_PERMISSIONS, true)) { + $permissions[] = $permission; + continue; + } + if ($manager->hasPermission($permission)) { $permissions[] = $permission; } diff --git a/services/nginx/app/routes/orderItemsRoute.php b/services/nginx/app/routes/orderItemsRoute.php index 13f1665c..e3a51fc0 100644 --- a/services/nginx/app/routes/orderItemsRoute.php +++ b/services/nginx/app/routes/orderItemsRoute.php @@ -81,9 +81,6 @@ class orderItemsRoute if (!$product->exists()) { $response->error('Product not found', 404); } - if ($product->requiresOrderItemNote() && trim((string)($notes ?? '')) === '') { - $response->error('Notes is required for this product', 400); - } $customerRuleViolation = (new customer_product_rule_service()) ->firstViolationForOrderItem((int)$data['order_id'], (int)$data['product_id'], $related_item_id); if ($customerRuleViolation !== null) { @@ -97,6 +94,9 @@ class orderItemsRoute ); $response->error($customerRuleViolation['message'], 400); } + if ($product->requiresOrderItemNote() && trim((string)($notes ?? '')) === '') { + $response->error('Notes is required for this product', 400); + } // Add the order item to the order This is done individually, to make the notes to the individual order items possible $order_items = (new order_items_o()); @@ -181,12 +181,12 @@ class orderItemsRoute $user = (new authentication())->get_user(); // Check if the request was successful if ($user) { - // Get the query data - $data = $_GET; - // Check if the required fields are set - if (!isset($data['id'])) { + // Get the order item id from the query string or request body + $itemIdRaw = $this->fromRequest('id'); + if ($itemIdRaw === null || $itemIdRaw === '') { $response->error('Order Item ID is required', 400); } + $data = ['id' => $itemIdRaw]; // Look up the order item to check department access $itemId = (int)$data['id']; $stmt = $db->prepare('SELECT oi.order_id FROM order_items oi WHERE oi.id = ? LIMIT 1'); diff --git a/services/nginx/app/routes/ordersRoute.php b/services/nginx/app/routes/ordersRoute.php index de71173b..7625c5e4 100644 --- a/services/nginx/app/routes/ordersRoute.php +++ b/services/nginx/app/routes/ordersRoute.php @@ -1373,11 +1373,7 @@ class ordersRoute { try { $user = (new authentication())->get_user(); - if ($user !== false && isset($user->customer_number) && (int)$user->customer_number->value() === $customerNumber) { - return true; - } - - return $this->hasDepartmentAccess((string)$departmentId); + return $user !== false && isset($user->customer_number) && (int)$user->customer_number->value() === $customerNumber; } catch (\Throwable) { return false; } diff --git a/services/nginx/app/tests/Api/LimitedBackofficeApiTest.php b/services/nginx/app/tests/Api/LimitedBackofficeApiTest.php index be5c1b9b..f1d0253f 100644 --- a/services/nginx/app/tests/Api/LimitedBackofficeApiTest.php +++ b/services/nginx/app/tests/Api/LimitedBackofficeApiTest.php @@ -1610,16 +1610,14 @@ it('rejects invalid limited backoffice employee contact details', function (): v it('includes list_departments in all active limited backoffice role presets', function (): void { foreach (['cashier', 'booking_coordinator', 'operations_lead', 'department_admin'] as $roleKey) { $permissions = limited_backoffice_role_preset_permissions($roleKey); - expect($permissions) - ->toContain('list_departments', "$roleKey must include list_departments"); + expect($permissions)->toContain('list_departments'); } }); it('includes list_department_daily_reports (dagsopgørelse) in all active limited backoffice role presets', function (): void { foreach (['cashier', 'booking_coordinator', 'operations_lead', 'department_admin'] as $roleKey) { $permissions = limited_backoffice_role_preset_permissions($roleKey); - expect($permissions) - ->toContain('list_department_daily_reports', "$roleKey must include list_department_daily_reports"); + expect($permissions)->toContain('list_department_daily_reports'); } }); @@ -1627,8 +1625,8 @@ it('includes list_notifications and list_own_notifications (Notifikationer) in a foreach (['cashier', 'booking_coordinator', 'operations_lead', 'department_admin'] as $roleKey) { $permissions = limited_backoffice_role_preset_permissions($roleKey); expect($permissions) - ->toContain('list_notifications', "$roleKey must include list_notifications") - ->toContain('list_own_notifications', "$roleKey must include list_own_notifications"); + ->toContain('list_notifications') + ->toContain('list_own_notifications'); } }); @@ -1636,8 +1634,8 @@ it('includes statistics_orders_new and statistics_bookings_new (Overblik) in all foreach (['cashier', 'booking_coordinator', 'operations_lead', 'department_admin'] as $roleKey) { $permissions = limited_backoffice_role_preset_permissions($roleKey); expect($permissions) - ->toContain('statistics_orders_new', "$roleKey must include statistics_orders_new") - ->toContain('statistics_bookings_new', "$roleKey must include statistics_bookings_new"); + ->toContain('statistics_orders_new') + ->toContain('statistics_bookings_new'); } });