Commit Graph
33 Commits
Author SHA1 Message Date
OpenClaw 51a87655d6 feat(auth): add scope-based access control to all existing routes (TRU-149)
Adds a scope-based access control layer to all 81 existing API routes.
Sits alongside existing session-cookie auth (does not replace it).

What this PR does:
- Audits every existing route and documents required scope per route
  (see documentation/auth/route-scope-audit.md)
- Adds classes/auth/scope.php with 10 scope constants and role→scope defaults
- Adds classes/auth/scope_middleware.php with requireScope/requireAnyScope/requireRole
- Applies require*() calls to all 81 existing routes
- Adds ScopeMiddlewareTest (unit, 178 lines) and RouteScopeTest (integration, 212 lines)

Coexistence note:
This branch's classes/auth/scope.php is a stub that will be replaced
by classes/auth/scope_registry.php (from TRU-145 / PR #396) when that
PR merges first. The two have compatible APIs.

Refs: TRU-149
2026-08-17 11:43:13 +00:00
Jeppe BOpenClaw Backend AgentJeppe Bjeppemaxclaw[bot] <bot@jeppemaxclaw.local>Bugfix Subagent
60222a7d91 fix(api): clarify user-invoice PUT validation so customers can invoice (TRU-128) (#382)
## Summary

Fixes **TRU-128** ("Jeg kan ikke fakturere") — a customer in
#afdelingsansvarlige could not invoice because the customer-facing
invoice PUT endpoint returned a misleading 400 error.

## Root cause

`PUT /collected-invoices` in
`services/nginx/app/routes/userInvoicesRoute.php` had two related bugs:

1. **Misleading error message** — the 'both fields missing' guard
errored with
   `'Missing required parameters: po_number, closed_at'`, which reads as
   if BOTH fields are required. The actual condition (`&&`) only fires
   when neither is set, so only one is required. Customers who tried
   different combinations kept getting the same error and concluded the
   system was broken.

2. **Inconsistent `closed_at` clearing** — the 'forbidden closed_at for
   non-superusers' guard fired for ANY present `closed_at` key,
   including `null` and `""`. That blocked customers from CLEARING a
   previously-set `closed_at`, even though the handler further down
   already nulls the field when it receives an empty value.

## Fix

- Reword the missing-fields error to state the actual contract:
  *"At least one of po_number or closed_at must be provided"*.
- Narrow the forbidden guard to *non-empty* `closed_at`, so customers
  can still pass `null` / `""` to clear a previously-set value.
  The clear-on-null/empty logic further down in the handler is unchanged
  — the guard now matches it.

## Test

`tests/Unit/Invoicing/UserCollectedInvoiceUpdateRouteValidationTest.php`
- Locks in the new error message.
- Locks in the new `$closed_at_is_non_empty` guard shape with the
  `if (self::isParametersSet(['closed_at'])) { ... }` pre-check.
- Locks in the regression: the previous 'any present closed_at -> 403'
  pattern is explicitly asserted to be absent.

## Files changed

- `services/nginx/app/routes/userInvoicesRoute.php`
-
`services/nginx/app/tests/Unit/Invoicing/UserCollectedInvoiceUpdateRouteValidationTest.php`

## Refs

- TRU-128
- Slack: #afdelingsansvarlige (kunde-rapport)

---------

Co-authored-by: OpenClaw Backend Agent <agent@openclaw.ai>
Co-authored-by: Jeppe B <jeppe@copenhagentruckwash.io>
Co-authored-by: jeppemaxclaw[bot] <bot@jeppemaxclaw.local>
Co-authored-by: Bugfix Subagent <bugfix-subagent@openclaw.local>
2026-08-16 18:20:03 +02:00
Jeppe B ab6c3ba5b6 Fix route permission instance calls (#344)
## Root cause

`route_t::hasPermission()` and `requirePermission()` are instance
methods. Route code was invoking them with `self::`; the new XL Vask
hall-scope helper made that call from a genuinely static context,
causing PHP to throw:

`Non-static method routes\\xlvaskUsageLogsRoute::hasPermission() cannot
be called statically`

## Changes

- Invoke route permission methods through `$this` across all 273
executable legacy calls in 45 route classes.
- Make `xlvaskUsageLogsRoute::allowedHallIdsForUser()` an instance
helper and update all 13 callers.
- Preserve the existing all-scope and own-scope hall selection rules.
- Add a token-aware regression test that rejects executable
`self::hasPermission()` and `self::requirePermission()` calls, while
ignoring comments.
- Add focused XL Vask tests for global scanner hall scope and
group-limited own scope.
- Update affected route contract assertions to the instance-call form.

## Verification

- PHP lint: all 53 changed PHP files
- Focused PHPStan: changed XL Vask route and both new regression tests —
clean
- Focused regression slice: 58 passed, 748 assertions
- Full local unit suite: 1,300 passed, 9,442 assertions (1 unrelated
existing warning, 1 environment skip)
- Full local API suite: 285 passed, 11,704 assertions
- Exact-SHA GitHub Tests workflow: all 7 jobs passed (unit, API,
integration, legacy, edge gateway, and supporting checks)
- Independent exact-SHA QA gate: PASS, no findings
- Independent exact-SHA security gate: PASS, no findings
- Independent exact-SHA reviewer gate: PASS, no findings
- Remote comparison: exactly one commit ahead of
`40b104abed7723a7d1b7028190ecda0e7aeef829`; all 53 remote blob hashes
matched the reviewed worktree

## Delivery state

Draft only for human review. No merge or deployment is included. Qodana
is skipped while the PR remains draft and is therefore not represented
as a passed gate.
2026-08-04 16:04:41 +02:00
Jeppe Bundgaard 870b88e707 Add assertError method to ApiResponse and enhance CI test failure handling 2026-07-08 13:03:33 +02:00
Jeppe Bundgaard f0b5479f30 Enhance department pricing functionality and improve related tests 2026-07-08 09:35:40 +02:00
Jeppe B b77efc538a Fix backend test gates and department product access 2026-07-07 22:16:37 +02:00
Jeppe Bundgaard 172a21c517 Implement department-specific customer pricing functionality 2026-07-07 17:27:56 +02:00
Jeppe Bundgaard 79185a3c76 Enhance product listing for customer booking sessions: allow access to booking-visible products without requiring additional permissions 2026-07-07 12:23:56 +02:00
Jeppe Bundgaard ed2736e528 Fix product null department permissions 2026-07-06 19:56:07 +02:00
Jeppe Bundgaard d47ea1d659 Add custom-only department pricing enforcement 2026-07-06 10:15:11 +02:00
Jeppe Bundgaard ae3657e7aa Add new API tests for order item note requirements, subuser route updates, and department lane status management
- Introduced tests for validating note requirements on order items.
- Updated subuser route management contract tests with new route coverage.
- Added endpoints to manage department lane and self-serve lane statuses, with associated tests.
2026-05-28 16:06:14 +02:00
Jeppe Bundgaard 0eddf69ae4 Replace getCustomerByIdOrCustomerNumber with getUserByCustomerNumber across services and remove deprecated method. 2026-01-06 15:50:59 +01:00
Jeppe Bundgaard 49589de98e Update getUserByCustomerNumber references to getCustomerByIdOrCustomerNumber and enhance null-checking in requireSelected. 2026-01-06 15:40:05 +01:00
Jeppe Bundgaard 2ec936225c Refactor booking notifications and product restriction logic
- Enable department notification for new bookings.
- Enhance Slack notification details for bookings, including customer, vehicle, and items.
- Replace `isGuest` with `isProductDetailsRestricted` for better clarity in `productsRoute`.
- Adjust product parsing to handle restricted product details consistently.
2025-11-27 10:25:53 +01:00
Jeppe Bundgaard 667947fcda Add guest user handling and product filtering in productsRoute
- Implement guest-specific product redactions (e.g., hide names, reset prices).
- Refactor `parseProduct` to include guest context for dynamic response handling.
- Add authentication checks and guest user handling for accurate permission validation.
- Update logging to include guest or user context in actions.
- Adjust product and addon parsing for consistent guest visibility.
2025-11-26 13:29:53 +01:00
Jeppe Bundgaard 32de29127a Fix product price typecasting and improve product parsing in productsRoute
- Corrected typecasting for product prices to ensure consistent integer values.
- Enhanced product parsing logic for better modularity and data handling in `productsRoute`.
2025-11-18 11:06:33 +01:00
Jeppe Bundgaard dfeffed63f Optimize product retrieval by department categories and improve filtering in productsRoute
- Refactored `getAllProductInDepartmentCategories` in `departments_o` using `array_reduce` for cleaner and more efficient category loop.
- Enhanced `productsRoute` to filter department-specific products using IDs for stricter matching.
2025-11-17 14:17:05 +01:00
Jeppe Bundgaard 2d121c67cd Add product retrieval by department categories and typecasting fixes
- Added methods in `department_categories_o`, `departments_o`, and `categories_o` to retrieve products associated with department categories.
- Updated `productsRoute` and `superuserDepartmentRoute` to fetch department-specific products.
- Fixed typecasting in product price assignments for improved data consistency.
2025-11-17 14:10:25 +01:00
Jeppe Bundgaard a22fc3fab0 Add support for including additional product categories in exterior washes
- Adjusted `productsRoute` to include products from categories "1" and "3" when category "6" is requested.
- Merged additional products to ensure comprehensive category listings.
2025-11-13 12:32:15 +01:00
Jeppe Bundgaard a6d427e3d3 Enhance error handling in productsRoute for customer retrieval
- Added exception handling with logging when fetching customer by ID fails.
- Improved safety checks to ensure customer existence before returning the object.
- Return `null` in case of failure to prevent unhandled errors.
2025-11-10 16:59:41 +01:00
Jeppe Bundgaard d06f0cedc3 Add new properties and routes for product and booking enhancements
- Added `virtual_cart` property in `bookings_o` and enhanced its structure method.
- Introduced `display_in_booking_form` and `order_priority` properties in `products_o` with updates to object structure, parsing, and routes.
- Enabled handling of product attributes `display_in_booking_form` and `order_priority` in `productsRoute`.
- Added `booked_invoice_id` reset logic in `collected_order_invoices_o`.
- Introduced `machineButtonPressRoute` to log button press incidents and send Slack notifications.
2025-10-28 09:58:29 +01:00
Jeppe Bundgaard e1a5618888 Refactor productsRoute response generation logic to support single-product retrieval and optimize price parsing. 2025-09-17 12:11:25 +02:00
Jeppe Bundgaard 102605f15b Add support for dynamic pricing in productsRoute
- Introduced methods to apply customer-specific discounts and department-based pricing to products and addons.
- Enhanced `productsRoute` to handle optional parameters (`customer_id`, `department_id`, `category`, `id`) for tailored pricing and filtering.
- Updated response generation to include adjusted prices for both products and options based on customer and department context.
- Added helper methods to streamline parameter validation and parsing in `productsRoute`.
- Extended `products_o` to support discount application logic for customer pricing.
2025-09-17 09:59:05 +02:00
Jeppe Bundgaard 97c448b5b6 Add is_wash field to products and support wash statistics in reports
- Introduced `is_wash` field to `products_o` for marking wash-related products.
- Updated `productsRoute` to handle `is_wash` in product creation and editing.
- Added `getTransactionsOnDateWashesCount` method in `department_daily_reports_o` for calculating wash-related transactions in reports.
- Adjusted department daily reports routes to include wash statistics output.
2025-09-03 14:03:02 +02:00
Jepp9350 e4ec92d66c Add Stripe payment intents support and product subscription flag
Introduced functionality for handling Stripe payment intents, including creation, retrieval, and cancellation. Added a subscription_allowed flag to products for enabling subscription-specific operations. Integrated the necessary backend endpoints, object property updates, and route handling logic.
2025-04-08 14:11:11 +02:00
Jepp9350 370760fbd3 Normalize data types for user prices and product attributes
Updated user price overrides and product attributes to enforce consistent data types. This improves data handling clarity and reduces type-related errors across the application.
2025-03-07 11:23:50 +01:00
Jepp9350 02a5b811bc Add support for 'requires_note' property in products module
Introduced a new 'requires_note' property to the product object, including its initialization, serialization, and integration in relevant routes. This change ensures the property can be set, retrieved, and properly processed in API requests. It also updates logging to capture changes to this field when editing products.
2025-03-06 14:49:33 +01:00
Jepp9350 4d593c2b17 Add department daily reports feature and improve product handling
Introduced functionality for managing department daily reports, including endpoints for creating, updating, listing, and viewing product sales data. Enhanced product handling in reports by adding support for water usage, notes, and detailed product sales metrics. These changes improve tracking and reporting accuracy across departments.
2025-03-04 11:39:38 +01:00
Jepp9350 8928cd375a Add booked_invoice_id property and optimize invoice handling
Introduce the booked_invoice_id property in collected_order_invoices_o for improved invoice management. Optimize performance by avoiding redundant requests to external systems when the booked_invoice_id is already set. Enhance routes to include the booked_invoice_id in relevant responses and ensure a consistent structure for associated data.
2025-03-04 08:24:33 +01:00
Jepp9350 d28cb172a0 Add permission definitions to route handlers
This update introduces explicit permission definitions for various route handlers across multiple routes. These changes enhance clarity and allow for more granular control over route access based on defined permissions. The updates ensure better manageability and scalability of endpoint permissions.
2025-02-20 14:33:42 +01:00
Jepp9350 67e6bb8bf2 Add product options and department categories API
Introduce endpoints for managing product options and department categories, including listing, creating, editing, and deleting functionalities. Updated related objects and traits to support new operations, including added array serialization methods and improved query handling for better flexibility.
2025-02-17 11:38:00 +01:00
Jepp9350 7525a89154 Refactor database operations and enhance routes for consistency
Refactored database methods to improve code readability, reusability, and error handling. Introduced input validation helper functions and parsing capabilities for objects with optional callbacks. Added new routes for handling categories and improved product-related functionality to align with the new architecture.
2025-02-12 16:39:52 +01:00
Jepp9350 707df910b0 Refactor: migrate files 2025-01-29 14:27:44 +01:00