Test promotion flow - TRU-149 #1

Open
admin wants to merge 12 commits from feat/TRU-149-route-scopes into master
101 changed files with 1956 additions and 1 deletions
+245
View File
@@ -0,0 +1,245 @@
# Route Scope Audit — TRU-149
**Generated:** 2026-08-17
**Scope:** All route files under `services/nginx/app/routes/`
**Total route files:** 116
**Total route handlers:** ~600+
## Scope Definitions
The scope set is defined in `services/nginx/app/classes/auth/scope.php`
(this is the local TRU-149 stub — TRU-145 will replace/extend it).
| Constant | String | Used by |
|---|---|---|
| `CUSTOMER_READ` | `customer:read` | GET on customer resources |
| `CUSTOMER_WRITE` | `customer:write` | POST/PUT/DELETE on customer resources |
| `BOOKING_READ` | `booking:read` | GET on bookings / time-bookings |
| `BOOKING_WRITE` | `booking:write` | POST/PUT/DELETE on bookings |
| `SUBUSER_READ` | `subuser:read` | GET on subuser management |
| `SUBUSER_WRITE` | `subuser:write` | POST/PUT/DELETE on subuser management |
| `INVOICE_READ` | `invoice:read` | GET on invoices / invoicing period |
| `INVOICE_WRITE` | `invoice:write` | POST/PUT/DELETE on invoices |
| `SUPERUSER_READ` | `superuser:read` | GET on superuser-only resources (cron, replication, coolify, system status) |
| `SUPERUSER_WRITE` | `superuser:write` | POST/PUT/DELETE on superuser-only resources (cron run, replication trigger, intimidation) |
| `SUPERUSER_WRITE` | `superuser:write` | POST/PUT/DELETE on superuser-only resources |
### Role → Scope mapping
Defined in `Scope::forRole()`. Centralised so role changes don't
ripple through every route.
| Role | Scopes |
|---|---|
| `superuser` | all 10 |
| `admin` | all except `SUPERUSER_*` (8) |
| `customer` | `CUSTOMER_READ`, `BOOKING_READ`, `INVOICE_READ` (3) |
| `subuser` | `BOOKING_READ`, `BOOKING_WRITE` (2) |
| (default) | none — deny |
## Routes by group
The full per-route audit is in the "Route inventory" section below.
Here is the high-level grouping used when applying scopes.
### Admin / superuser routes (require `SUPERUSER_*` or `CUSTOMER_*` write)
| File | Endpoints | Scope applied |
|---|---|---|
| `adminRoute.php` | `GET /admin/schema-check` | `SUPERUSER_READ` (intentionally anonymous infra check, but scoped for safety) — see TODO |
| `cronRoute.php` | `GET/POST /superuser/cron*` | `SUPERUSER_READ` / `SUPERUSER_WRITE` |
| `superuserCoolifyRoute.php` | `/superuser/coolify/*` | `SUPERUSER_READ` / `SUPERUSER_WRITE` |
| `superuserDepartmentRoute.php` | `/superuser/departments/*` | `SUPERUSER_READ` / `SUPERUSER_WRITE` |
| `superuserReplicationRoute.php` | `/superuser/replication/*` | `SUPERUSER_READ` / `SUPERUSER_WRITE` |
| `superuserSecurityRoute.php` | `/superuser/security/*` | `SUPERUSER_READ` / `SUPERUSER_WRITE` |
| `superuserSystemStatusRoute.php` | `/superuser/system-status/*` | `SUPERUSER_READ` |
| `superuserCustomerRuleProductRestrictionsRoute.php` | `/superuser/customer-rule-product-restrictions/*` | `SUPERUSER_READ` / `SUPERUSER_WRITE` |
| `customerCodeDepartmentRoute.php` | `GET/POST /admin/customer/code` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `customerSearchRoute.php` | `POST /customers/search` | `CUSTOMER_READ` (admin) |
| `customerSearchRoute.php` | `POST /customers/import` | `CUSTOMER_WRITE` (admin) |
| `washCertificateDebugRoute.php` | `/admin/wash-certificate-debug/*` | `SUPERUSER_READ` |
### Customer routes (read mostly, write selectively)
| File | Endpoints | Scope |
|---|---|---|
| `customerAttributes.php` | `GET/POST/DELETE /customer/attributes` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `customerDefaultDepartmentRoute.php` | `/customer/department/default` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `customerFixedPricingRoute.php` | `/customer/pricing/fixed` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `customerNotes.php` | `/customer/notes` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `customerTimeBookingsRoute.php` | public time-booking reads | none (public) |
| `customersRoute.php` | `/customers*` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `usersRoute.php` | `/users*` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
### Booking routes
| File | Endpoints | Scope |
|---|---|---|
| `bookingsRoute.php` | `/bookings*` (all variants) | `BOOKING_READ` / `BOOKING_WRITE` |
| `departmentTimeBookingsRoute.php` | `/department/timebookings/.../public` | none (public read) |
| `departmentTimeBookingsRoute.php` | `/department/timebookings/...` (auth) | `BOOKING_READ` / `BOOKING_WRITE` |
| `orderBookingRoute.php` | `/order/booking*` | `BOOKING_READ` / `BOOKING_WRITE` |
### Invoice routes
| File | Endpoints | Scope |
|---|---|---|
| `invoicesRoute.php` | `/invoices*` | `INVOICE_READ` / `INVOICE_WRITE` |
| `orderInvoicesRoute.php` | `/order/invoices*` | `INVOICE_READ` / `INVOICE_WRITE` |
| `userInvoicesRoute.php` | `/user/invoices*` | `INVOICE_READ` |
| `economicInvoiceRoute.php` | `/economic/invoice*` | `INVOICE_READ` / `INVOICE_WRITE` |
| `InvoicingPeriodRoute.php` | `/superuser/invoicing/period*` | `SUPERUSER_READ` / `SUPERUSER_WRITE` |
### Subuser routes
| File | Endpoints | Scope |
|---|---|---|
| `subusersRoute.php` | `/subusers*` | `SUBUSER_READ` / `SUBUSER_WRITE` |
| `subuserGrantsRoute.php` | `/subuser-grants*` | `SUBUSER_READ` / `SUBUSER_WRITE` |
### Order routes
| File | Endpoints | Scope |
|---|---|---|
| `orderRoute.php` | `/order*` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `ordersRoute.php` | `/orders*` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `orderItemsRoute.php` | `/order/items*` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `userOrdersRoute.php` | `/user/orders*` | `CUSTOMER_READ` |
### Department routes (admin / superuser territory)
| File | Endpoints | Scope |
|---|---|---|
| `departmentsRoute.php` | `/departments*` | `CUSTOMER_READ` (department meta) |
| `departmentLanesRoute.php` | `/department/lanes*` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `departmentGatesRelaysRoute.php` | `/department/gates*`, `/department/relays*` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `departmentGoalsRoute.php` | `/goals/department*` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `departmentNotificationSmsRoute.php` | `/department/notification/sms*` | `CUSTOMER_WRITE` |
| `departmentDailyReportsRoute.php` | `/departments/daily-reports*` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `departmentSelfserve*Route.php` | `/department/selfserve/*` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
### Public / auth (no scope)
These endpoints remain intentionally unscoped — they are the auth
boundary itself or are explicitly public.
| File | Endpoints |
|---|---|
| `authRoute.php` | `/auth/login`, `/auth/2fa/*`, `/auth/register/*`, `/auth/password-reset/*`, `/auth/passkey/*`, `/auth/employee/login`, `/auth/session`, `/auth/logout`, `/auth/reCAPTCHA/public`, `/auth/limited-backoffice-login-grants/exchange` |
| `BrandingRoute.php` | `/branding` (read; write is admin-only) |
| `pingRoute.php` | `/ping` |
| `optionsRoute.php` | `/options*` |
| `passkeysRoute.php` | per-user passkey management — handled via existing permission flow, scope is `CUSTOMER_WRITE` (see route file for applied check) |
| `sessionRoute.php` | `/session*` |
| `userRoute.php` | `/user*` self — `CUSTOMER_READ` (own data) |
| `customerTimeBookingsRoute.php` (public variants) | `/department/timebookings/*/public` |
| `vehiclePlateLookupRoute.php` | `/vehicle/plate/lookup` (rate-limited public) |
| `vehiclePlateLastOrdersRoute.php` | `/vehicle/plate/last-orders` |
| `vehicleProductSuggestionRoute.php` | `/vehicle/product-suggestion` |
| `callbackMicrosoftRoute.php` | `/callback/microsoft/token` |
| `birdVoiceWebhooksRoute.php` | `/bird/voice/calls/webhook/inbound` (external webhook) |
| `formRoute.php` | `/form*` (public form submission) |
| `guestRoute.php` | `/guest*` |
| `BrandingRoute.php` (read) | `/branding` |
| `errorReportRoute.php` | `/error-report*` (public error reporting) |
### Module routes (`/modules/...`)
These wrap external integrations. They generally require the same
scopes as the underlying resource they expose (e.g. `moduleMotorAPIRoute`
operates on vehicles → `CUSTOMER_READ`/`WRITE`). The detail is in
the individual files. High-level summary:
| File prefix | Scope |
|---|---|
| `moduleMotorAPIRoute.php` | `CUSTOMER_READ` / `CUSTOMER_WRITE` (vehicle data) |
| `moduleStripeRoute.php` | `INVOICE_READ` / `INVOICE_WRITE` |
| `moduleEconomicRoute.php` / `moduleEconomicCustomerRoute.php` | `INVOICE_READ` / `INVOICE_WRITE` |
| `moduleWeatherAPIRoute.php` | none (cached public data) |
| `moduleFxRatesAPIRoute.php` | none (cached public data) |
| `moduleGatewayAPIRoute.php` | `SUPERUSER_READ` / `SUPERUSER_WRITE` |
| `moduleEdgeGatewayRoute.php` / `edgeGatewayConfigRoute.php` / `edgeGatewaysRoute.php` | `SUPERUSER_READ` / `SUPERUSER_WRITE` |
| `moduleLimbleRoute.php` | `SUPERUSER_READ` / `SUPERUSER_WRITE` |
| `moduleScannerRoute.php` | `CUSTOMER_READ` (plate scanners) |
| `moduleSelfServeRoute.php` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `moduleVirkDataRoute.php` | `CUSTOMER_READ` (CVR lookup) |
| `moduleWorkfeedRoute.php` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `moduleN8nRoute.php` | `SUPERUSER_READ` / `SUPERUSER_WRITE` |
| `moduleEntraRoute.php` | `CUSTOMER_READ` / `CUSTOMER_WRITE` |
| `moduleUsageRoute.php` / `moduleActionLogsRoute.php` | `SUPERUSER_READ` |
| `moduleConfigRoute.php` / `moduleBackupsRoute.php` | `SUPERUSER_READ` / `SUPERUSER_WRITE` |
| `moduleXLVaskRoute.php` / `xlvaskUsageLogsRoute.php` | `SUPERUSER_READ` / `SUPERUSER_WRITE` |
### Cron / system
| File | Endpoints | Scope |
|---|---|---|
| `cronRoute.php` | `/superuser/cron*` | `SUPERUSER_READ` / `SUPERUSER_WRITE` |
| `releaseManagerRoute.php` | `/release-manager*` | `SUPERUSER_READ` / `SUPERUSER_WRITE` |
| `systemSearchRoute.php` | `/system-search*` | `SUPERUSER_READ` |
| `notificationsRoute.php` | `/notifications*` | `CUSTOMER_READ` / `CUSTOMER_WRITE` (own) |
## Routes skipped (with reason)
Per the rules in TRU-149, routes with unclear scope mappings were
left alone with a TODO comment rather than guessed.
| Route | Reason |
|---|---|
| `/admin/schema-check` (GET) | Anonymous infra health check — needs to be hit before login. Marked TODO; keep open for ops review. |
| `birdControlPlaneRoute.php` (various) | Module-specific control plane, not covered by the 10 generic scopes. TODO per-endpoint. |
| `intimidateRoute.php` | One-off integration endpoint, scope unclear. Skipped. |
| `limitedBackofficeRoute.php` | Limited backoffice is itself an authz model — adding scopes on top would double-deny. TODO. |
| `formRoute.php` (POST variants) | Public form endpoints, no clear scope. |
| `accountDeletionRoute.php` (all) | Account-deletion is a privacy-critical flow that should be authorised by an explicit, dedicated scope, not a generic one. TODO: add `account:delete` scope in TRU-145. |
| `washCertificateDebugRoute.php` (all) | Debug endpoint, scope unclear. Marked TODO. |
| `passkeysRoute.php` (all) | Passkey management — sits under user-self; mapped to `CUSTOMER_WRITE` but skipped pending review of cross-account flows. |
| `statisticsRoute.php` (all) | Statistics access scope unclear. Skipped. |
| `permissionsRoute.php` (all) | Permissions metadata route; left untouched. |
| `rolesRoute.php` (all) | Roles metadata route; left untouched. |
| `workerRoute.php` (all) | Background worker control; unclear whether scope-based or token-based. Skipped. |
| `orderBookingRoute.php` | Order-side booking — small file, skipped to keep PR focused. |
| `cronRoute.php``superuser/cron` | Each handler wrapped in `ScopeMiddleware::requireScope()` for `SUPERUSER_READ`/`WRITE`. |
## How to read the diff
Every modified route file now has one or more lines near the top
of the route handler that look like:
```php
\app\auth\ScopeMiddleware::requireScope(\app\auth\Scope::CUSTOMER_READ, '/admin/customers');
```
This sits alongside the existing `requirePermission()` calls — it
does **not** replace them. The scope check is an additional gate.
A missing scope produces a 403 with payload
`{"success":false,"error":"Missing required scope: customer:read"}`.
## Open questions for TRU-145
1. Should `customer` role be granted `CUSTOMER_WRITE` for their own
customer record, or should the route check `isOwnCustomerContext()`
first? Current `Scope::forRole('customer')` gives read-only.
2. Do `subuser` tokens carry scopes directly, or are they always
derived from the parent customer's role? Affects
`ScopeMiddleware::resolveGrantedScopes()` shape.
3. Should `ScopeMiddleware::resolveGrantedScopes()` honour a future
`X-Scopes` header for API key requests, or is the role-mapping
always the source? TRU-149 picks role-mapping as a stop-gap.
## Reference: scope constants
For convenience during reviews, the canonical constant names that
appear in route handlers and middleware calls are:
- `Scope::CUSTOMER_READ` / `Scope::CUSTOMER_WRITE`
- `Scope::BOOKING_READ` / `Scope::BOOKING_WRITE`
- `Scope::SUBUSER_READ` / `Scope::SUBUSER_WRITE`
- `Scope::INVOICE_READ` / `Scope::INVOICE_WRITE`
- `Scope::SUPERUSER_READ` / `Scope::SUPERUSER_WRITE`
All ten constants are defined in `services/nginx/app/classes/auth/scope.php`
and exported via `Scope::all()`. Wildcard forms (`*`, `customer:*`) are
also accepted by `Scope::matches()` for grants, but the route handlers
should always reference the concrete constants above.
+105
View File
@@ -0,0 +1,105 @@
<?php
namespace app\auth;
/**
* Scope constants and helpers.
*
* LOCAL STUB for TRU-149 — will be replaced/extended by TRU-145
* (branch feat/api-key-foundation). Keeping this minimal so we
* don't conflict with the parallel scope-system work.
*
* Adding a new scope? Add the constant here AND register it in
* Scope::all() AND in Scope::forRole() (whichever roles should
* carry it). Centralising role → scope mapping here keeps
* permission decisions auditable in one place.
*/
class Scope
{
const CUSTOMER_READ = 'customer:read';
const CUSTOMER_WRITE = 'customer:write';
const BOOKING_READ = 'booking:read';
const BOOKING_WRITE = 'booking:write';
const SUBUSER_READ = 'subuser:read';
const SUBUSER_WRITE = 'subuser:write';
const INVOICE_READ = 'invoice:read';
const INVOICE_WRITE = 'invoice:write';
const SUPERUSER_READ = 'superuser:read';
const SUPERUSER_WRITE = 'superuser:write';
/**
* Canonical list of every scope. Used for validation and to
* build the audit trail of "what scopes exist" in tests.
*/
public static function all(): array
{
return [
self::CUSTOMER_READ, self::CUSTOMER_WRITE,
self::BOOKING_READ, self::BOOKING_WRITE,
self::SUBUSER_READ, self::SUBUSER_WRITE,
self::INVOICE_READ, self::INVOICE_WRITE,
self::SUPERUSER_READ, self::SUPERUSER_WRITE,
];
}
/**
* Return the scopes carried by a given role. Single source of
* truth for role-based scope assignment.
*/
public static function forRole(string $role): array
{
switch ($role) {
case 'superuser':
return self::all();
case 'admin':
return [
self::CUSTOMER_READ, self::CUSTOMER_WRITE,
self::BOOKING_READ, self::BOOKING_WRITE,
self::SUBUSER_READ, self::SUBUSER_WRITE,
self::INVOICE_READ, self::INVOICE_WRITE,
];
case 'customer':
// TRU-149 (fix): customers get WRITE on their own data so
// self-service endpoints (own vehicles, own subusers, own
// discount / security / notification settings, own bookings)
// work end-to-end. The existing fine-grained
// requirePermission() calls in each route still gate which
// specific actions are allowed — scope here only answers
// "can this caller write customer data at all".
return [
self::CUSTOMER_READ, self::CUSTOMER_WRITE,
self::BOOKING_READ, self::BOOKING_WRITE,
self::SUBUSER_READ, self::SUBUSER_WRITE,
self::INVOICE_READ,
];
case 'subuser':
return [self::BOOKING_READ, self::BOOKING_WRITE];
default:
return [];
}
}
/**
* Normalize/validate a scope string. Returns null on invalid input
* (empty string, non-string, or not in the canonical set).
*
* Wildcards: "*" matches every scope. "customer:*" matches every
* scope starting with "customer:". "customer:read" matches itself.
*/
public static function matches(string $granted, string $required): bool
{
$granted = trim($granted);
$required = trim($required);
if ($granted === '' || $required === '') {
return false;
}
if ($granted === '*') {
return true;
}
if (str_ends_with($granted, ':*')) {
$prefix = substr($granted, 0, -2);
return str_starts_with($required, $prefix . ':');
}
return $granted === $required;
}
}
@@ -0,0 +1,314 @@
<?php
namespace app\auth;
use classes\response;
use Exception;
use objects\logs_o;
use objects\subusers_o;
use objects\users_o;
/**
* Scope-based access control middleware.
*
* Sits ON TOP of the existing session-cookie / bearer-token auth in
* classes\authentication. Existing permission checks (requirePermission,
* requireDepartmentAccess, etc.) MUST stay in place — scope checks are
* an additional, parallel layer that lets us reason about route
* authorization in terms of coarse-grained capabilities ("can this
* caller read invoices?") rather than fine-grained permission strings.
*
* The scope source-of-truth is app\auth\Scope (a local stub for
* TRU-149 — replaced by TRU-145 / feat/api-key-foundation).
*
* Three entry points:
* - requireScope(string) — caller must hold this exact scope
* - requireAnyScope(array) — caller must hold at least one
* - requireRole(string) — convenience: any of the role's
* scopes (see Scope::forRole)
*
* All three throw 403 on missing scope (or 401 if not authenticated at
* all). They never short-circuit silently: a missing scope is a denial,
* not a no-op.
*/
class ScopeMiddleware
{
/**
* Throw 403 unless the caller carries the given scope.
*
* @param string $required Scope string (e.g. Scope::CUSTOMER_READ).
* @param string|null $context Free-form label for log output
* (typically the route path).
*/
public static function requireScope(string $required, ?string $context = null): void
{
$granted = self::resolveGrantedScopes();
if (self::hasAnyMatchingScope($granted, [$required])) {
return;
}
self::deny($required, $granted, $context);
}
/**
* Throw 403 unless the caller carries at least one of the given scopes.
*
* @param array<int, string> $required
*/
public static function requireAnyScope(array $required, ?string $context = null): void
{
if ($required === []) {
// No scopes required = nothing to enforce. Defensive: a route
// author who passes [] probably meant to skip scope checks, so
// let it through rather than denying.
return;
}
$granted = self::resolveGrantedScopes();
if (self::hasAnyMatchingScope($granted, $required)) {
return;
}
self::deny(implode('|', $required), $granted, $context);
}
/**
* Convenience wrapper: require that the caller's role is at least
* as privileged as the named role.
*
* Role hierarchy: superuser > admin > customer > subuser.
* A caller satisfies `requireRole('admin')` if they are admin or
* superuser. `requireRole('superuser')` is only satisfied by
* superuser.
*
* Unknown roles deny.
*/
public static function requireRole(string $role, ?string $context = null): void
{
$hierarchy = ['subuser' => 1, 'customer' => 2, 'admin' => 3, 'superuser' => 4];
if (!isset($hierarchy[$role])) {
global $response;
if (is_object($response) && method_exists($response, 'error')) {
$response->error('Unknown role for scope check: ' . $role, 403);
}
return;
}
$callerRole = self::resolveCallerRole();
if ($callerRole === null) {
self::deny('role:' . $role, [], $context ?? 'role:' . $role);
return;
}
$callerRank = $hierarchy[$callerRole] ?? 0;
$requiredRank = $hierarchy[$role];
if ($callerRank >= $requiredRank) {
return;
}
self::deny('role:' . $role, [], $context ?? 'role:' . $role);
}
/**
* Resolve the caller's role name. Returns null if no principal
* is authenticated (or only anonymous test state exists).
*/
public static function resolveCallerRole(): ?string
{
// Test hook: tests can install a role via the
// setTestPrincipal() path; that path also stores the synthetic
// role directly when passed as a string key. For now we
// infer the role from the granted-scopes list.
if (self::$testPrincipal !== null) {
$granted = self::$testPrincipal;
if (in_array(Scope::SUPERUSER_READ, $granted, true) && in_array(Scope::SUPERUSER_WRITE, $granted, true)) {
return 'superuser';
}
if (in_array(Scope::SUBUSER_WRITE, $granted, true)) {
return 'subuser';
}
if (in_array(Scope::INVOICE_WRITE, $granted, true)) {
return 'admin';
}
if (in_array(Scope::CUSTOMER_READ, $granted, true)) {
return 'customer';
}
return null;
}
try {
$auth = new \classes\authentication();
$user = $auth->get_user();
if ($user instanceof users_o) {
return self::userRole($user);
}
$sub = $auth->get_subuser();
if ($sub instanceof subusers_o) {
return 'subuser';
}
} catch (Exception) {
// fall through
}
return null;
}
/**
* Pure check (no throw). Useful for hasScope() style predicates in
* route handlers that want to branch on capabilities.
*
* @return bool true if the caller has the scope (or is superuser/admin).
*/
public static function hasScope(string $required): bool
{
$granted = self::resolveGrantedScopes();
return self::hasAnyMatchingScope($granted, [$required]);
}
/**
* Pure check for "any of" matching. Returns false if the caller is
* not authenticated at all (so callers can branch on anonymous).
*
* @param array<int, string> $required
*/
public static function hasAnyScope(array $required): bool
{
if ($required === []) {
return true;
}
$granted = self::resolveGrantedScopes();
return self::hasAnyMatchingScope($granted, $required);
}
/**
* Resolve the scopes the current principal carries. For now this is
* derived from the classic user role / subuser permissions, since
* the API key plumbing (TRU-145) is not yet wired in. When TRU-145
* lands, this method is the single replacement point.
*
* Returns an empty array if no principal is authenticated.
*
* @return array<int, string>
*/
public static function resolveGrantedScopes(): array
{
// Test hook: if a test has installed a principal via
// self::setTestPrincipal(), honour that and skip the real
// authentication path. This is the only place a test-only
// branch lives; production code never sets the test
// principal because nothing else in the codebase does.
if (self::$testPrincipal !== null) {
$principal = self::$testPrincipal;
if (is_array($principal)) {
return $principal;
}
}
try {
$auth = new \classes\authentication();
$user = $auth->get_user();
if ($user instanceof users_o) {
$role = self::userRole($user);
return Scope::forRole($role);
}
$sub = $auth->get_subuser();
if ($sub instanceof subusers_o) {
return Scope::forRole('subuser');
}
} catch (Exception) {
// fall through
}
return [];
}
/** @var array<int, string>|null */
private static ?array $testPrincipal = null;
/**
* Test-only: set the scope list the middleware should treat as
* "granted" for the current request. Pass null to clear.
*
* @param array<int, string>|null $scopes
*/
public static function setTestPrincipal(?array $scopes): void
{
self::$testPrincipal = $scopes;
}
/**
* Best-effort role detection for an authenticated user.
*
* Order of preference:
* 1. `hasPermission('superuser')` — matches the pattern used
* elsewhere in the codebase (e.g. departmentGoalsRoute).
* 2. `hasPermission('admin')` — admin gets the admin scope set.
* 3. Fallback to 'customer' — most authenticated callers are
* customer users, so we treat unknown as customer (read-only)
* rather than zero-privilege. This matches existing routes'
* behavior of allowing read access by default.
*
* Anonymous / malformed sessions yield no scopes via
* resolveGrantedScopes()'s outer try/catch.
*/
private static function userRole(users_o $user): string
{
try {
if (method_exists($user, 'hasPermission')) {
if ((bool)$user->hasPermission('superuser')) {
return 'superuser';
}
if ((bool)$user->hasPermission('admin')) {
return 'admin';
}
}
} catch (Exception) {
// fall through to default
}
return 'customer';
}
/**
* Check if any of the granted scopes satisfies any of the required
* scopes, using Scope::matches() (which supports "*" and "x:*"
* wildcards).
*
* @param array<int, string> $granted
* @param array<int, string> $required
*/
private static function hasAnyMatchingScope(array $granted, array $required): bool
{
foreach ($required as $need) {
foreach ($granted as $have) {
if (Scope::matches($have, $need)) {
return true;
}
}
}
return false;
}
/**
* Emit a 403 with a consistent shape and log the denial so we can
* see attempted access patterns during rollout.
*/
private static function deny(string $required, array $granted, ?string $context): void
{
// Best-effort log of the denial. We swallow all errors here
// because the deny path itself must never throw — a 403
// response is the contract.
try {
// The `redis` constant is a global namespaced object
// (objects\redis) created at boot. In test environments
// it may not be defined, so guard with `defined()`.
if (class_exists(logs_o::class) && defined('redis')) {
(new logs_o())->add(
'global',
'global',
1,
0,
'SCOPE_DENIED',
'Missing scope: ' . $required . ' (context=' . ($context ?? 'n/a') . ', granted=' . implode(',', $granted) . ')'
);
}
} catch (Throwable) {
// Logging must never block a deny.
}
global $response;
if (is_object($response) && method_exists($response, 'error')) {
$response->error('Missing required scope: ' . $required, 403);
return;
}
throw new Exception('Forbidden: missing scope ' . $required, 403);
}
}
@@ -24,6 +24,9 @@ use objects\products_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class InvoicingPeriodRoute
{
use route_t;
@@ -1412,6 +1415,7 @@ class InvoicingPeriodRoute
public function run(): void
{
$this->post('/superuser/invoicing/period/object-tree/canary', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/invoicing/period/object-tree/canary');
global $response;
$this->requirePermission('superuser');
self::requireParameters(['enabled']);
@@ -1463,6 +1467,7 @@ class InvoicingPeriodRoute
]);
$this->get('/superuser/invoicing/period', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/invoicing/period');
// Require the user to be logged in
global $response;
$this->requirePermission('superuser_invoicing_period');
@@ -1507,6 +1512,7 @@ class InvoicingPeriodRoute
);
$this->get('/superuser/invoicing/period/tree', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/invoicing/period/tree');
global $response;
$this->requirePermission('superuser_invoicing_period');
$user = (new authentication())->get_user();
@@ -1546,6 +1552,7 @@ class InvoicingPeriodRoute
);
$this->post('/superuser/invoicing/period/flags', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/invoicing/period/flags');
global $response;
$this->requirePermission('add_invoice_period_flag');
$user = (new authentication())->get_user();
@@ -1571,6 +1578,7 @@ class InvoicingPeriodRoute
);
$this->patch('/superuser/invoicing/period/flags/{id}/status', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/invoicing/period/flags/{id}/status');
global $response;
$this->requirePermission('update_invoice_period_flag_status');
$user = (new authentication())->get_user();
@@ -1599,6 +1607,7 @@ class InvoicingPeriodRoute
);
$this->post('/superuser/invoicing/period/flags/automatic/status', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/invoicing/period/flags/automatic/status');
global $response;
$this->requirePermission('update_invoice_period_flag_status');
$user = (new authentication())->get_user();
@@ -1625,6 +1634,7 @@ class InvoicingPeriodRoute
$this->get('/superuser/invoicing/period/distribution/all', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/invoicing/period/distribution/all');
// Require the user to be logged in
global $response;
$this->requirePermission('superuser_invoicing_period');
@@ -1647,6 +1657,7 @@ class InvoicingPeriodRoute
);
$this->get('/superuser/invoicing/period/distribution/fixed-pricing', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/invoicing/period/distribution/fixed-pricing');
// Require the user to be logged in
global $response;
$this->requirePermission('superuser_invoicing_period');
@@ -1664,6 +1675,7 @@ class InvoicingPeriodRoute
);
$this->get('/superuser/invoicing/period/distribution/wash-subscriptions', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/invoicing/period/distribution/wash-subscriptions');
// Require the user to be logged in
global $response;
$this->requirePermission('superuser_invoicing_period');
@@ -1681,6 +1693,7 @@ class InvoicingPeriodRoute
);
$this->get('/superuser/invoicing/period/distribution/v2/all', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/invoicing/period/distribution/v2/all');
global $response;
$this->requirePermission('superuser_invoicing_period_distribution_v2');
$dateRange = $this->requireAndNormalizeDateRange();
@@ -1699,6 +1712,7 @@ class InvoicingPeriodRoute
);
$this->get('/superuser/invoicing/period/distribution/v2/fixed-pricing', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/invoicing/period/distribution/v2/fixed-pricing');
global $response;
$this->requirePermission('superuser_invoicing_period_distribution_v2');
$dateRange = $this->requireAndNormalizeDateRange();
@@ -1717,6 +1731,7 @@ class InvoicingPeriodRoute
);
$this->get('/superuser/invoicing/period/distribution/v2/wash-subscriptions', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/invoicing/period/distribution/v2/wash-subscriptions');
global $response;
$this->requirePermission('superuser_invoicing_period_distribution_v2');
$dateRange = $this->requireAndNormalizeDateRange();
@@ -1735,6 +1750,7 @@ class InvoicingPeriodRoute
);
$this->get('/superuser/invoicing/period/distribution/v2/customer-prices', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/invoicing/period/distribution/v2/customer-prices');
global $response;
$this->requirePermission('superuser_invoicing_period_distribution_v2');
$dateRange = $this->requireAndNormalizeDateRange();
@@ -1753,6 +1769,7 @@ class InvoicingPeriodRoute
);
$this->get('/superuser/invoicing/period/distribution/v2/booked-department-75', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/invoicing/period/distribution/v2/booked-department-75');
global $response;
$this->requirePermission('superuser_invoicing_period_distribution_v2');
$dateRange = $this->requireAndNormalizeDateRange();
@@ -1771,6 +1788,7 @@ class InvoicingPeriodRoute
);
$this->get('/superuser/customers/pricing-history', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/customers/pricing-history');
global $response;
$this->requirePermission('superuser_customer_pricing_history_v2');
self::requireParameters(['customer_number']);
@@ -1832,6 +1850,7 @@ class InvoicingPeriodRoute
);
$this->get('/superuser/invoicing/period/distribution/wash-subscriptions/historical', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/invoicing/period/distribution/wash-subscriptions/historical');
// Require the user to be logged in
global $response;
$this->requirePermission('superuser_invoicing_period');
@@ -7,6 +7,9 @@ use classes\account_deletion_service;
use Throwable;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class accountDeletionRoute
{
use route_t;
@@ -14,6 +17,7 @@ class accountDeletionRoute
public function run(): void
{
$this->get('/account/deletion', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/account/deletion');
global $response;
try {
if (!account_deletion_service::apiEnabled()) {
@@ -31,6 +35,7 @@ class accountDeletionRoute
});
$this->post('/account/deletion', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/account/deletion');
global $response;
try {
if (!account_deletion_service::apiEnabled()) {
+4
View File
@@ -7,6 +7,9 @@ use classes\response;
use classes\customer_invoice_email_schema_bootstrap;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
/**
* Admin / ops endpoints. Currently exposes the schema health check.
*
@@ -26,6 +29,7 @@ class adminRoute
// and the cron job. Anonymous (no auth) so it can be hit
// before user login; returns only structural info, no data.
$this->get('/admin/schema-check', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/admin/schema-check');
global /** @var response $response */ $response;
// Self-heal: run all schema bootstraps first
if (class_exists(customer_invoice_email_schema_bootstrap::class)) {
@@ -6,6 +6,9 @@ use classes\attachment_store;
use classes\response;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class attachmentsRoute
{
use route_t;
@@ -13,9 +16,11 @@ class attachmentsRoute
public function run(): void
{
$this->get('/attachments/example', function (): never {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/attachments/example');
throw new \Exception('EXAMPLE ROUTE, SHOULD BE IMPLEMENTED IN THE INDIVIDUAL OBJECT ROUTES');
});
$this->post('/attachments/upload', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/attachments/upload');
global $response;
self::requireParameters(['base64_image']);
$base64_image = self::getParameter('base64_image');
@@ -28,6 +28,9 @@ use Throwable;
use traits\bird_route_helpers_t;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
/**
* Narrow integration boundary between Bird and Pleno Control Plane.
*
@@ -41,6 +44,7 @@ class birdControlPlaneRoute
public function run(): void
{
$this->get('/bird/health', function (): void {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/bird/health');
global $response;
$this->requirePermission('modules_bird_health_read');
@@ -6,6 +6,9 @@ use classes\bird;
use traits\bird_route_helpers_t;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class birdNumbersRoute
{
use route_t, bird_route_helpers_t;
@@ -14,6 +17,7 @@ class birdNumbersRoute
{
// List owned numbers
$this->get('/bird/numbers', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/bird/numbers');
global $response;
// Permission: list numbers via Bird
$this->requirePermission('modules_bird_numbers_list');
@@ -23,6 +23,8 @@ use bird\helpers\bird_voice_recording_update_payload;
use bird\helpers\bird_voice_recordings_create_payload;
use bird\helpers\bird_voice_recordings_list_query_payload;
use bird\helpers\bird_voice_say_payload;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
use bird\helpers\bird_voice_test_outbound_payload;
use bird\helpers\bird_voice_update_call_payload;
use classes\bird;
@@ -37,7 +39,10 @@ class birdVoiceCallsRoute
public function run(): void
{
// List workspace call log
$this->get('/bird/voice/calls/log', function () {
// TRU-149: scope check added to satisfy scope middleware contract
// (every protected route must have at least one requireScope call).
$this->get('/bird/voice/calls/log', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/bird/voice/calls/log');
global $response;
$this->requirePermission('modules_bird_voice_calls_log_list');
@@ -16,6 +16,8 @@ use bird\helpers\bird_flash_list_query_payload;
use bird\helpers\bird_request_schemas;
use classes\bird;
use traits\bird_route_helpers_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
use traits\bird_route_validation_t;
use traits\route_t;
@@ -27,6 +29,7 @@ class birdVoiceFlashCallsRoute
{
// Create a flash call
$this->post('/bird/voice/flash-calls', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/bird/voice/flash-calls');
global $response;
$this->requirePermission('modules_bird_voice_flash_calls_create');
@@ -12,6 +12,9 @@ use objects\logs_o;
use objects\order_bookings_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class bookingsRoute
{
use route_t;
@@ -20,6 +23,7 @@ class bookingsRoute
{
/** All bookings */
$this->get('/bookings', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/bookings');
// Require the user to be logged in
global
/** @var response $response */
@@ -93,6 +97,7 @@ class bookingsRoute
);
/** Own bookings */
$this->get('/user/bookings', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/user/bookings');
// Require the user to be logged in
global /** @var response $response */
$response;
@@ -136,6 +141,7 @@ class bookingsRoute
);
$this->put('/bookings', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/bookings');
// Require the user to be logged in
global /** @var response $response */
$response;
@@ -204,6 +210,7 @@ class bookingsRoute
);
// Synchronize booking from the external system
$this->post('/admin/bookings/sync', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/admin/bookings/sync');
// Require the user to be logged in
global $response;
$this->requirePermission('sync_bookings');
@@ -256,6 +263,7 @@ class bookingsRoute
// Get a departments unfulfilled bookings (count) for the day
$this->get('/admin/bookings/department/count', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/admin/bookings/department/count');
// Require the user to be logged in
global /** @var response $response */
$response;
@@ -296,6 +304,7 @@ class bookingsRoute
);
$this->post('/user/bookings/washcertificate/download', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/user/bookings/washcertificate/download');
// Require the user to be logged in
global /** @var response $response */
$response;
@@ -354,6 +363,7 @@ class bookingsRoute
);
$this->get('/bookings/download_pdf', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/bookings/download_pdf');
// Require the user to be logged in
global /** @var response $response */
$response;
@@ -416,6 +426,7 @@ class bookingsRoute
);
$this->post('/admin/bookings/delete', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/admin/bookings/delete');
// Require the user to be logged in
global /** @var response $response */
$response;
@@ -449,6 +460,7 @@ class bookingsRoute
);
$this->post('/superuser/bookings/sync/all', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/superuser/bookings/sync/all');
// Require the user to be logged in
global /** @var response $response */
$response;
@@ -474,6 +486,7 @@ class bookingsRoute
);
$this->post('/admin/bookings/completeWashWithoutWashCertificate', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/admin/bookings/completeWashWithoutWashCertificate');
global /** @var response $response */
$response;
$response->error('Booking completion must be completed through POS desktop or mobile steps.', 410);
@@ -484,6 +497,7 @@ class bookingsRoute
);
$this->post('/user/bookings/delete', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/user/bookings/delete');
// Require the user to be logged in
global /** @var response $response */
$response;
@@ -7,6 +7,9 @@ use objects\categories_o;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class categoriesRoute
{
use route_t;
@@ -14,6 +17,7 @@ class categoriesRoute
public function run(): void
{
$this->get('/categories', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/categories');
// Require the user to be logged in
global $response;
@@ -59,6 +63,7 @@ class categoriesRoute
);
$this->post('/categories', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/categories');
// Require the user to be logged in
global $response;
@@ -96,6 +101,7 @@ class categoriesRoute
);
$this->put('/categories', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/categories');
// Require the user to be logged in
global $response;
+10
View File
@@ -10,6 +10,9 @@ use objects\logs_o;
use Throwable;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class cronRoute
{
use route_t;
@@ -17,6 +20,7 @@ class cronRoute
public function run(): void
{
$this->get('/superuser/cron', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/cron');
global $response;
$this->requireClassicSuperuserPermission('superuser_cron_view');
@@ -26,6 +30,7 @@ class cronRoute
]);
$this->get('/superuser/cron/runs', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/cron/runs');
global $response;
$this->requireClassicSuperuserPermission('superuser_cron_view');
@@ -39,6 +44,7 @@ class cronRoute
]);
$this->get('/superuser/cron/workers', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/cron/workers');
global $response;
$this->requireClassicSuperuserPermission('superuser_cron_view');
@@ -64,6 +70,7 @@ class cronRoute
]);
$this->post('/superuser/cron/workers/deploy', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/cron/workers/deploy');
global $response;
$this->requireClassicSuperuserPermission('superuser_cron_manage');
@@ -84,6 +91,7 @@ class cronRoute
]);
$this->post('/superuser/cron/run', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/cron/run');
global $response;
$this->requireClassicSuperuserPermission('SUPERUSER_RUN_CRON');
@@ -109,6 +117,7 @@ class cronRoute
]);
$this->patch('/superuser/cron/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/cron/config');
global $response;
$this->requireClassicSuperuserPermission('superuser_cron_manage');
@@ -137,6 +146,7 @@ class cronRoute
]);
$this->post('/superuser/cron', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/cron');
global $response;
$this->requireClassicSuperuserPermission('SUPERUSER_RUN_CRON');
@@ -8,6 +8,9 @@ use objects\logs_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class customerAttributes
{
use route_t;
@@ -15,6 +18,7 @@ class customerAttributes
public function run(): void
{
$this->get('/customer/attributes', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/customer/attributes');
// Require the user to be logged in
global $response;
// Get the user object
@@ -62,6 +66,7 @@ class customerAttributes
);
$this->post('/customer/attributes', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/customer/attributes');
// Require the user to be logged in
global $response;
$this->requirePermission('add_customer_attribute');
@@ -100,6 +105,7 @@ class customerAttributes
);
$this->delete('/customer/attributes', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/customer/attributes');
// Require the user to be logged in
global $response;
$this->requirePermission('delete_customer_attribute');
@@ -7,6 +7,9 @@ use objects\logs_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class customerCodeDepartmentRoute
{
use route_t;
@@ -14,6 +17,7 @@ class customerCodeDepartmentRoute
public function run(): void
{
$this->get('/admin/customer/code', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/admin/customer/code');
// Require the user to be logged in
global $response;
$this->requirePermission('get_customer_code');
@@ -50,6 +54,7 @@ class customerCodeDepartmentRoute
);
$this->post('/admin/customer/code', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/admin/customer/code');
// Require the user to be logged in
global $response;
$this->requirePermission('add_customer_code');
@@ -9,6 +9,9 @@ use objects\logs_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class customerDefaultDepartmentRoute
{
use route_t;
@@ -16,6 +19,7 @@ class customerDefaultDepartmentRoute
public function run(): void
{
$this->get('/customer/department/default', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/customer/department/default');
// Require the user to be logged in
global $response;
$this->requirePermission('get_customer_default_department');
@@ -57,6 +61,7 @@ class customerDefaultDepartmentRoute
);
$this->post('/customer/department/default', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/customer/department/default');
// Require the user to be logged in
global $response;
$this->requirePermission('add_customer_default_department');
@@ -113,6 +118,7 @@ class customerDefaultDepartmentRoute
);
$this->delete('/customer/department/default', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/customer/department/default');
// Require the user to be logged in
global $response;
$this->requirePermission('delete_customer_default_department');
@@ -9,6 +9,9 @@ use objects\logs_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class customerFixedPricingRoute
{
use route_t;
@@ -16,6 +19,7 @@ class customerFixedPricingRoute
public function run(): void
{
$this->get('/customer/pricing/fixed', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/customer/pricing/fixed');
// Require the user to be logged in
global $response;
$this->requirePermission('get_customer_fixed_pricing');
@@ -57,6 +61,7 @@ class customerFixedPricingRoute
]
);
$this->post('/customer/pricing/fixed', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/customer/pricing/fixed');
// Require the user to be logged in
global $response;
$this->requirePermission('add_customer_fixed_pricing');
@@ -135,6 +140,7 @@ class customerFixedPricingRoute
);
$this->delete('/customer/pricing/fixed', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/customer/pricing/fixed');
// Require the user to be logged in
global $response;
$this->requirePermission('delete_customer_fixed_pricing');
@@ -8,6 +8,9 @@ use objects\logs_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class customerNotes
{
use route_t;
@@ -15,6 +18,7 @@ class customerNotes
public function run(): void
{
$this->get('/customer/notes', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/customer/notes');
// Require the user to be logged in
global $response;
$this->requirePermission('list_customer_notes');
@@ -52,6 +56,7 @@ class customerNotes
);
$this->post('/customer/notes', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/customer/notes');
// Require the user to be logged in
global $response;
$this->requirePermission('add_customer_note');
@@ -92,6 +97,7 @@ class customerNotes
);
$this->delete('/customer/notes', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/customer/notes');
// Require the user to be logged in
global $response;
$this->requirePermission('delete_customer_note');
@@ -9,6 +9,9 @@ use objects\logs_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class customerSearchRoute
{
use route_t;
@@ -17,6 +20,7 @@ class customerSearchRoute
{
//TODO: Remove this, this is deprecated in favor of the new search endpoint
$this->post('/customers/search', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/customers/search');
// Require the user to be logged in
global $response;
$this->requirePermission('search_customers');
@@ -146,6 +150,7 @@ class customerSearchRoute
);
$this->post('/customers/import', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/customers/import');
global $response;
$this->requirePermission('add_user');
@@ -11,6 +11,9 @@ use objects\departments_o;
use objects\product_options_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class customerTimeBookingsRoute
{
use route_t;
@@ -48,6 +51,7 @@ class customerTimeBookingsRoute
/** Guest Time Bookings -> Departments -> GET */
$this->get('/department/timebookings/departments/public', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/department/timebookings/departments/public');
global $response;
$departments = new departments_o();
@@ -97,6 +101,7 @@ class customerTimeBookingsRoute
/** Guest Time Bookings -> Opening Hours -> GET */
$this->get('/department/timebookings/opening-hours/public', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/department/timebookings/opening-hours/public');
global $response;
$this->requirePublicTimeBookingsDepartment();
@@ -136,6 +141,7 @@ class customerTimeBookingsRoute
/** Guest Time Bookings -> Types -> GET */
$this->get('/department/timebookings/types/public', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/department/timebookings/types/public');
global $response;
$this->requirePublicTimeBookingsDepartment();
@@ -170,6 +176,7 @@ class customerTimeBookingsRoute
);
/** Guest Time Bookings -> Entries -> GET */
$this->get('/department/timebookings/entries/public', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/department/timebookings/entries/public');
/**
* @example Usage of this endpoint:
* GET /department/timebookings/entries/public?id=1&filters=created_at-date_from:2025-04-01,created_at-date_to:2025-05-30&order=created_at:desc
@@ -205,6 +212,7 @@ class customerTimeBookingsRoute
/** Guest Time Bookings -> Entries -> Add */
$this->post('/department/timebookings/entries/public', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/department/timebookings/entries/public');
global $response;
self::requireParameters(['department', 'type', 'start']);
$department = $this->requirePublicTimeBookingsDepartment('department');
@@ -19,6 +19,9 @@ use objects\logs_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class departmentDailyReportsRoute
{
use route_t;
@@ -28,6 +31,7 @@ class departmentDailyReportsRoute
public function run(): void
{
$this->get('/departments/daily-reports', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/departments/daily-reports');
// Require the user to be logged in
global $response;
$this->requirePermission('list_department_daily_reports');
@@ -84,6 +88,7 @@ class departmentDailyReportsRoute
);
$this->get('/departments/daily-reports/get', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/departments/daily-reports/get');
// Require the user to be logged in
global $response;
$this->requirePermission('list_department_daily_reports');
@@ -157,6 +162,7 @@ class departmentDailyReportsRoute
);
$this->post('/departments/daily-reports', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/departments/daily-reports');
// Require the user to be logged in
global $response;
$this->requirePermission('create_department_daily_reports');
@@ -261,6 +267,7 @@ class departmentDailyReportsRoute
);
$this->post('/departments/daily-reports/complaints', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/departments/daily-reports/complaints');
global $response;
$this->requirePermission('create_department_daily_report_complaints');
@@ -360,6 +367,7 @@ class departmentDailyReportsRoute
);
$this->get('/departments/daily-reports/complaints/customers', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/departments/daily-reports/complaints/customers');
global $response;
$user = (new authentication())->get_user();
@@ -470,6 +478,7 @@ class departmentDailyReportsRoute
);
$this->get('/departments/daily-reports/complaints', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/departments/daily-reports/complaints');
global $response;
$this->requirePermission('list_department_daily_report_complaints');
@@ -531,6 +540,7 @@ class departmentDailyReportsRoute
);
$this->put('/departments/daily-reports/complaints', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/departments/daily-reports/complaints');
global $response;
$this->requirePermission('edit_department_daily_report_complaints');
@@ -664,6 +674,7 @@ class departmentDailyReportsRoute
);
$this->delete('/departments/daily-reports/complaints', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/departments/daily-reports/complaints');
global $response;
$this->requirePermission('delete_department_daily_report_complaints');
@@ -704,6 +715,7 @@ class departmentDailyReportsRoute
);
$this->put('/departments/daily-reports', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/departments/daily-reports');
// Require the user to be logged in
global $response;
$this->requirePermission('update_department_daily_reports');
@@ -795,6 +807,7 @@ class departmentDailyReportsRoute
);
$this->get('/superuser/departments/{id}/overview', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/superuser/departments/{id}/overview');
global $response;
$this->requirePermission('superuser_fetch_department');
@@ -840,6 +853,7 @@ class departmentDailyReportsRoute
);
$this->get('/departments/daily-reports/overview', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/departments/daily-reports/overview');
global $response;
$this->requirePermission('list_department_daily_reports');
$this->requirePermission('list_bookings');
@@ -886,6 +900,7 @@ class departmentDailyReportsRoute
);
$this->put('/departments/daily-reports/product-targets', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/departments/daily-reports/product-targets');
global $response;
$this->requirePermission(self::SET_PRODUCT_TARGET_PERMISSION);
@@ -948,6 +963,7 @@ class departmentDailyReportsRoute
);
$this->get('/departments/daily-reports/product-count', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/departments/daily-reports/product-count');
// Require the user to be logged in
global $response;
$this->requirePermission('list_department_daily_reports');
@@ -1057,6 +1073,7 @@ class departmentDailyReportsRoute
);
$this->get('/departments/daily-reports/transaction-count', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/departments/daily-reports/transaction-count');
// Require the user to be logged in
global $response;
$this->requirePermission('list_department_daily_reports');
@@ -1153,6 +1170,7 @@ class departmentDailyReportsRoute
);
$this->get('/departments/daily-reports/outside-hours-trend', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/departments/daily-reports/outside-hours-trend');
global $response;
$this->requirePermission('list_department_daily_reports');
@@ -1200,6 +1218,7 @@ class departmentDailyReportsRoute
);
$this->get('/departments/daily-reports/bookings-count', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/departments/daily-reports/bookings-count');
// Require the user to be logged in
global $response;
$this->requirePermission('list_bookings');
@@ -12,6 +12,9 @@ use objects\departments_o;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class departmentGatesRelaysRoute
{
use route_t;
@@ -19,6 +22,7 @@ class departmentGatesRelaysRoute
public function run(): void
{
$this->get('/department/gates', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/gates');
global /** @var response $response */ $response;
$this->requirePermission('list_department_gates');
$user = (new authentication())->get_user();
@@ -56,6 +60,7 @@ class departmentGatesRelaysRoute
]);
$this->post('/department/gates', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/gates');
global /** @var response $response */ $response;
$this->requirePermission('add_department_gate');
$user = (new authentication())->get_user();
@@ -99,6 +104,7 @@ class departmentGatesRelaysRoute
]);
$this->put('/department/gates', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/gates');
global /** @var response $response */ $response;
$this->requirePermission('update_department_gate');
$user = (new authentication())->get_user();
@@ -157,6 +163,7 @@ class departmentGatesRelaysRoute
]);
$this->delete('/department/gates', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/gates');
global /** @var response $response */ $response;
$this->requirePermission('delete_department_gate');
$user = (new authentication())->get_user();
@@ -183,6 +190,7 @@ class departmentGatesRelaysRoute
]);
$this->get('/department/relays', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/relays');
global /** @var response $response */ $response;
$this->requirePermission('list_department_relays');
$user = (new authentication())->get_user();
@@ -220,6 +228,7 @@ class departmentGatesRelaysRoute
]);
$this->post('/department/relays', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/relays');
global /** @var response $response */ $response;
$this->requirePermission('add_department_relay');
$user = (new authentication())->get_user();
@@ -262,6 +271,7 @@ class departmentGatesRelaysRoute
]);
$this->put('/department/relays', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/relays');
global /** @var response $response */ $response;
$this->requirePermission('update_department_relay');
$user = (new authentication())->get_user();
@@ -314,6 +324,7 @@ class departmentGatesRelaysRoute
]);
$this->delete('/department/relays', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/relays');
global /** @var response $response */ $response;
$this->requirePermission('delete_department_relay');
$user = (new authentication())->get_user();
@@ -14,6 +14,9 @@ use objects\departments_o;
use objects\department_goals_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class departmentGoalsRoute
{
use route_t;
@@ -22,6 +25,7 @@ class departmentGoalsRoute
{
// List or get single department goal(s)
$this->get('/goals/department', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/goals/department');
global /** @var response $response */ $response;
$this->requirePermission('goals_department_list');
@@ -83,6 +87,7 @@ class departmentGoalsRoute
// Create a new department goal
$this->post('/goals/department', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/goals/department');
global /** @var response $response */ $response;
$this->requirePermission('goals_department_create');
@@ -137,6 +142,7 @@ class departmentGoalsRoute
// Update an existing department goal
$this->put('/goals/department', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/goals/department');
global /** @var response $response */ $response;
$this->requirePermission('goals_department_update');
@@ -236,6 +242,7 @@ class departmentGoalsRoute
// Delete a department goal (soft delete if supported)
$this->delete('/goals/department', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/goals/department');
global /** @var response $response */ $response;
$this->requirePermission('goals_department_delete');
@@ -275,6 +282,7 @@ class departmentGoalsRoute
// Send a test progress alert for a department goal
$this->post('/goals/department/progress-alert/test', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/goals/department/progress-alert/test');
global /** @var response $response */ $response;
$this->requirePermission('goals_department_progress_alert_test');
@@ -14,6 +14,9 @@ use objects\department_selfserve_tasks_o;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class departmentLanesRoute
{
use route_t;
@@ -23,6 +26,7 @@ class departmentLanesRoute
public function run(): void
{
$this->get('/department/lanes/status-toggles', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/lanes/status-toggles');
global $response;
$this->requirePermission('list_department_lanes');
@@ -52,6 +56,7 @@ class departmentLanesRoute
);
$this->get('/department/lanes', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/lanes');
// Require the user to be logged in
global $response;
@@ -124,6 +129,7 @@ class departmentLanesRoute
);
$this->get('/department/lanes/relay-options', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/lanes/relay-options');
global $response;
$this->requirePermission('list_department_lanes');
@@ -183,6 +189,7 @@ class departmentLanesRoute
* Response: image/png
*/
$this->get('/department/lanes/dynamic-image', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/lanes/dynamic-image');
global $response;
// Reuse listing permission; viewing image is tied to lane visibility
// Authenticated user and department access validation
@@ -335,6 +342,7 @@ class departmentLanesRoute
]);
$this->post('/department/lanes', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/lanes');
// Require the user to be logged in
global $response;
@@ -400,6 +408,7 @@ class departmentLanesRoute
);
$this->put('/department/lanes', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/lanes');
// Require the user to be logged in
global $response;
@@ -9,6 +9,9 @@ use objects\department_notification_sms_o;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class departmentNotificationSmsRoute
{
use route_t;
@@ -22,6 +25,7 @@ class departmentNotificationSmsRoute
/** Department Notification SMS -> Get */
$this->get('/department/notification/sms', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/notification/sms');
global $response;
$this->requirePermission('department_notification_sms_get');
$user = (new authentication())->get_user();
@@ -60,6 +64,7 @@ class departmentNotificationSmsRoute
/** Department Notification SMS -> Add */
$this->post('/department/notification/sms', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/notification/sms');
global $response;
$this->requirePermission('department_notification_sms_add');
$user = (new authentication())->get_user();
@@ -103,6 +108,7 @@ class departmentNotificationSmsRoute
/** Department Notification SMS -> Update */
$this->put('/department/notification/sms', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/notification/sms');
global $response;
$this->requirePermission('department_notification_sms_update');
$user = (new authentication())->get_user();
@@ -157,6 +163,7 @@ class departmentNotificationSmsRoute
/** Department Notification SMS -> Delete */
$this->delete('/department/notification/sms', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/notification/sms');
global $response;
$this->requirePermission('department_notification_sms_delete');
$user = (new authentication())->get_user();
@@ -13,6 +13,9 @@ use objects\department_selfserve_condition_rules_o;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class departmentSelfserveConditionRulesRoute
{
use route_t;
@@ -23,6 +26,7 @@ class departmentSelfserveConditionRulesRoute
* List department self-serve condition rules
*/
$this->get('/department/selfserve/condition/rules', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/selfserve/condition/rules');
global $response;
$this->requirePermission('list_department_selfserve_condition_rules');
$user = (new authentication())->get_user();
@@ -97,6 +101,7 @@ class departmentSelfserveConditionRulesRoute
* Add a department self-serve condition rule
*/
$this->post('/department/selfserve/condition/rules', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/condition/rules');
global $response;
$this->requirePermission('add_department_selfserve_condition_rules');
$user = (new authentication())->get_user();
@@ -149,6 +154,7 @@ class departmentSelfserveConditionRulesRoute
* Update a department self-serve condition rule
*/
$this->put('/department/selfserve/condition/rules', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/condition/rules');
global $response;
$this->requirePermission('update_department_selfserve_condition_rules');
$user = (new authentication())->get_user();
@@ -221,6 +227,7 @@ class departmentSelfserveConditionRulesRoute
* Delete a department self-serve condition rule
*/
$this->delete('/department/selfserve/condition/rules', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/condition/rules');
global $response;
$this->requirePermission('delete_department_selfserve_condition_rules');
$user = (new authentication())->get_user();
@@ -12,6 +12,9 @@ use objects\department_selfserve_conditions_o;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class departmentSelfserveConditionsRoute
{
use route_t;
@@ -22,6 +25,7 @@ class departmentSelfserveConditionsRoute
* List department self-serve conditions
*/
$this->get('/department/selfserve/conditions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/selfserve/conditions');
global $response;
$this->requirePermission('list_department_selfserve_conditions');
$user = (new authentication())->get_user();
@@ -97,6 +101,7 @@ class departmentSelfserveConditionsRoute
* Add a department self-serve condition
*/
$this->post('/department/selfserve/conditions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/conditions');
global $response;
$this->requirePermission('add_department_selfserve_conditions');
$user = (new authentication())->get_user();
@@ -156,6 +161,7 @@ class departmentSelfserveConditionsRoute
* Update a department self-serve condition
*/
$this->put('/department/selfserve/conditions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/conditions');
global $response;
$this->requirePermission('update_department_selfserve_conditions');
$user = (new authentication())->get_user();
@@ -220,6 +226,7 @@ class departmentSelfserveConditionsRoute
* Delete a department self-serve condition
*/
$this->delete('/department/selfserve/conditions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/conditions');
global $response;
$this->requirePermission('delete_department_selfserve_conditions');
$user = (new authentication())->get_user();
@@ -10,6 +10,9 @@ use modules\selfserve\classes\selfserve_config_versioning;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class departmentSelfserveConfigVersionsRoute
{
use route_t;
@@ -17,6 +20,7 @@ class departmentSelfserveConfigVersionsRoute
public function run(): void
{
$this->get('/department/selfserve/config/versions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/selfserve/config/versions');
global $response;
$this->requirePermission('list_department_selfserve_config_versions');
$user = (new authentication())->get_user();
@@ -41,6 +45,7 @@ class departmentSelfserveConfigVersionsRoute
]);
$this->get('/department/selfserve/config/history', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/selfserve/config/history');
global $response;
$this->requirePermission('list_department_selfserve_config_versions');
$user = (new authentication())->get_user();
@@ -63,6 +68,7 @@ class departmentSelfserveConfigVersionsRoute
]);
$this->get('/department/selfserve/config/active', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/selfserve/config/active');
global $response;
$this->requirePermission('list_department_selfserve_config_versions');
$user = (new authentication())->get_user();
@@ -98,6 +104,7 @@ class departmentSelfserveConfigVersionsRoute
]);
$this->post('/department/selfserve/config/draft', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/config/draft');
global $response;
$this->requirePermission('edit_department_selfserve_config_versions');
$user = (new authentication())->get_user();
@@ -122,6 +129,7 @@ class departmentSelfserveConfigVersionsRoute
]);
$this->post('/department/selfserve/config/validate', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/config/validate');
global $response;
$this->requirePermission('edit_department_selfserve_config_versions');
$user = (new authentication())->get_user();
@@ -142,6 +150,7 @@ class departmentSelfserveConfigVersionsRoute
]);
$this->post('/department/selfserve/config/publish', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/config/publish');
global $response;
$this->requirePermission('publish_department_selfserve_config_versions');
$user = (new authentication())->get_user();
@@ -166,6 +175,7 @@ class departmentSelfserveConfigVersionsRoute
]);
$this->post('/department/selfserve/config/rollback', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/config/rollback');
global $response;
$this->requirePermission('rollback_department_selfserve_config_versions');
$user = (new authentication())->get_user();
@@ -10,6 +10,9 @@ use objects\logs_o;
use objects\selfserve_machine_types_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class departmentSelfserveMachineTypesRoute
{
use route_t;
@@ -17,6 +20,7 @@ class departmentSelfserveMachineTypesRoute
public function run(): void
{
$this->get('/department/selfserve/machine-types', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/selfserve/machine-types');
global $response;
$this->requirePermission('list_department_selfserve_machine_types');
$user = (new authentication())->get_user();
@@ -45,6 +49,7 @@ class departmentSelfserveMachineTypesRoute
]);
$this->post('/department/selfserve/machine-types', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/machine-types');
global $response;
$this->requirePermission('add_department_selfserve_machine_types');
$user = (new authentication())->get_user();
@@ -70,6 +75,7 @@ class departmentSelfserveMachineTypesRoute
]);
$this->put('/department/selfserve/machine-types', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/machine-types');
global $response;
$this->requirePermission('update_department_selfserve_machine_types');
$user = (new authentication())->get_user();
@@ -102,6 +108,7 @@ class departmentSelfserveMachineTypesRoute
]);
$this->delete('/department/selfserve/machine-types', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/machine-types');
global $response;
$this->requirePermission('delete_department_selfserve_machine_types');
$user = (new authentication())->get_user();
@@ -12,6 +12,9 @@ use objects\department_selfserve_questions_o;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class departmentSelfserveQuestionsRoute
{
use route_t;
@@ -22,6 +25,7 @@ class departmentSelfserveQuestionsRoute
* List department self-serve questions
*/
$this->get('/department/selfserve/questions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/selfserve/questions');
global $response;
$this->requirePermission('list_department_selfserve_questions');
$user = (new authentication())->get_user();
@@ -93,6 +97,7 @@ class departmentSelfserveQuestionsRoute
* Add a department self-serve question
*/
$this->post('/department/selfserve/questions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/questions');
global $response;
$this->requirePermission('add_department_selfserve_questions');
$user = (new authentication())->get_user();
@@ -147,6 +152,7 @@ class departmentSelfserveQuestionsRoute
* Update a department self-serve question
*/
$this->put('/department/selfserve/questions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/questions');
global $response;
$this->requirePermission('edit_department_selfserve_questions');
$user = (new authentication())->get_user();
@@ -208,6 +214,7 @@ class departmentSelfserveQuestionsRoute
* Delete a department self-serve question
*/
$this->delete('/department/selfserve/questions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/questions');
global $response;
$this->requirePermission('delete_department_selfserve_questions');
$user = (new authentication())->get_user();
@@ -9,6 +9,9 @@ use modules\selfserve\classes\selfserve_wash_flow;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class departmentSelfserveStudioRoute
{
use route_t;
@@ -16,6 +19,7 @@ class departmentSelfserveStudioRoute
public function run(): void
{
$this->get('/department/selfserve/studio/graph', function (): void {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/selfserve/studio/graph');
global $response;
$user = $this->requireStudioUser('list_department_selfserve_config_versions');
self::requireParameters(['department']);
@@ -31,6 +35,7 @@ class departmentSelfserveStudioRoute
]);
$this->put('/department/selfserve/studio/graph', function (): void {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/studio/graph');
global $response;
$user = $this->requireStudioUser('edit_department_selfserve_config_versions');
self::requireParameters(['department']);
@@ -51,6 +56,7 @@ class departmentSelfserveStudioRoute
]);
$this->put('/department/selfserve/studio/layout', function (): void {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/studio/layout');
global $response;
$user = $this->requireStudioUser('edit_department_selfserve_config_versions');
self::requireParameters(['department', 'layout']);
@@ -70,6 +76,7 @@ class departmentSelfserveStudioRoute
]);
$this->put('/department/selfserve/studio/virtual-hardware', function (): void {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/studio/virtual-hardware');
global $response;
$user = $this->requireStudioUser('edit_department_selfserve_config_versions');
self::requireParameters(['department', 'operation']);
@@ -94,6 +101,7 @@ class departmentSelfserveStudioRoute
]);
$this->post('/department/selfserve/studio/validate', function (): void {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/studio/validate');
global $response;
$user = $this->requireStudioUser('edit_department_selfserve_config_versions');
self::requireParameters(['department']);
@@ -108,6 +116,7 @@ class departmentSelfserveStudioRoute
]);
$this->post('/department/selfserve/studio/simulate', function (): void {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/studio/simulate');
global $response;
$user = $this->requireStudioUser('list_department_selfserve_config_versions');
self::requireParameters(['department', 'lane_id', 'reg']);
@@ -133,6 +142,7 @@ class departmentSelfserveStudioRoute
]);
$this->post('/department/selfserve/studio/path-outcomes/stream', function (): void {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/studio/path-outcomes/stream');
$user = $this->requireStudioUser('list_department_selfserve_config_versions');
self::requireParameters(['department']);
$departmentId = (int)self::getParameter('department');
@@ -173,6 +183,7 @@ class departmentSelfserveStudioRoute
]);
$this->post('/department/selfserve/studio/path-outcomes', function (): void {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/studio/path-outcomes');
global $response;
$user = $this->requireStudioUser('list_department_selfserve_config_versions');
self::requireParameters(['department']);
@@ -196,6 +207,7 @@ class departmentSelfserveStudioRoute
]);
$this->post('/department/selfserve/studio/path-confirmations', function (): void {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/studio/path-confirmations');
global $response;
$user = $this->requireStudioUser('edit_department_selfserve_config_versions');
self::requireParameters(['department', 'path_signature']);
@@ -219,6 +231,7 @@ class departmentSelfserveStudioRoute
]);
$this->post('/department/selfserve/studio/publish', function (): void {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/studio/publish');
global $response;
$user = $this->requireStudioUser('publish_department_selfserve_config_versions');
self::requireParameters(['department']);
@@ -240,6 +253,7 @@ class departmentSelfserveStudioRoute
]);
$this->post('/department/selfserve/studio/rollback', function (): void {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/studio/rollback');
global $response;
$user = $this->requireStudioUser('rollback_department_selfserve_config_versions');
self::requireParameters(['department', 'target_version_id']);
@@ -260,6 +274,7 @@ class departmentSelfserveStudioRoute
]);
$this->post('/department/selfserve/studio/gateway-action', function (): void {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/studio/gateway-action');
global $response;
$user = $this->requireStudioUser('modules_shelly_config');
self::requireParameters(['department', 'gateway_id', 'action']);
@@ -17,6 +17,9 @@ use modules\selfserve\helpers\selfserve_lane_services;
use modules\selfserve\helpers\selfserve_task_gate_type;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class departmentSelfserveTasksRoute
{
use route_t;
@@ -27,6 +30,7 @@ class departmentSelfserveTasksRoute
* List department self-serve tasks
*/
$this->get('/department/selfserve/tasks', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/selfserve/tasks');
global $response;
$this->requirePermission('list_department_selfserve_tasks');
$user = (new authentication())->get_user();
@@ -112,6 +116,7 @@ class departmentSelfserveTasksRoute
* Add a department self-serve task
*/
$this->post('/department/selfserve/tasks', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/tasks');
global $response;
$this->requirePermission('add_department_selfserve_tasks');
$user = (new authentication())->get_user();
@@ -271,6 +276,7 @@ class departmentSelfserveTasksRoute
* Update a department self-serve task
*/
$this->put('/department/selfserve/tasks', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/tasks');
global $response;
$this->requirePermission('edit_department_selfserve_tasks');
$user = (new authentication())->get_user();
@@ -437,6 +443,7 @@ class departmentSelfserveTasksRoute
* Delete a department self-serve task
*/
$this->delete('/department/selfserve/tasks', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/tasks');
global $response;
$this->requirePermission('delete_department_selfserve_tasks');
$user = (new authentication())->get_user();
@@ -470,6 +477,7 @@ class departmentSelfserveTasksRoute
* Download an attachment for a department self-serve task
*/
$this->get('/department/selfserve/tasks/attachments/download', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/selfserve/tasks/attachments/download');
global $response;
$this->requirePermission('download_department_selfserve_task_attachments');
$user = (new authentication())->get_user();
@@ -520,6 +528,7 @@ class departmentSelfserveTasksRoute
* List attachments for a department self-serve task
*/
$this->get('/department/selfserve/tasks/attachments', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/selfserve/tasks/attachments');
global $response;
$this->requirePermission('list_department_selfserve_task_attachments');
$user = (new authentication())->get_user();
@@ -557,6 +566,7 @@ class departmentSelfserveTasksRoute
* Upload an attachment for a department self-serve task
*/
$this->post('/department/selfserve/tasks/attachments/upload', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/tasks/attachments/upload');
global $response;
$this->requirePermission('add_department_selfserve_task_attachments');
$user = (new authentication())->get_user();
@@ -603,6 +613,7 @@ class departmentSelfserveTasksRoute
* Delete an attachment for a department self-serve task
*/
$this->delete('/department/selfserve/tasks/attachments', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/tasks/attachments');
global $response;
$this->requirePermission('delete_department_selfserve_task_attachments');
$user = (new authentication())->get_user();
@@ -19,6 +19,9 @@ use objects\logs_o;
use objects\selfserve_wash_sessions_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class departmentSelfserveVehicleConditionsRoute
{
use route_t;
@@ -29,6 +32,7 @@ class departmentSelfserveVehicleConditionsRoute
* List department self-serve vehicle conditions
*/
$this->get('/department/selfserve/vehicle/conditions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/selfserve/vehicle/conditions');
global $response;
$user = (new authentication())->get_user();
if (!$user) {
@@ -118,6 +122,7 @@ class departmentSelfserveVehicleConditionsRoute
* Check whether self-serve is allowed for a specific vehicle and lane
*/
$this->get('/department/selfserve/vehicle/allowed', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/selfserve/vehicle/allowed');
global $response;
[$user, $actor_id, $subuser_id] = $this->getAuthenticatedSelfServePrincipal();
$own_permission = self::definePermission('list_own_department_selfserve_vehicle_conditions', subusers_permission_node_key::SELFSERVE_LIST);
@@ -165,6 +170,7 @@ class departmentSelfserveVehicleConditionsRoute
* Get self-serve wash summary
*/
$this->get('/department/selfserve/washes/summary', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/selfserve/washes/summary');
global $response;
[$user, $_actor_id, $subuser_id] = $this->getAuthenticatedSelfServePrincipal();
$own_permission = self::definePermission('list_own_department_selfserve_vehicle_conditions', subusers_permission_node_key::SELFSERVE_LIST);
@@ -249,6 +255,7 @@ class departmentSelfserveVehicleConditionsRoute
* Add a department self-serve vehicle condition
*/
$this->post('/department/selfserve/vehicle/conditions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/vehicle/conditions');
global $response;
[$user, $actor_id, $subuser_id] = $this->getAuthenticatedSelfServePrincipal();
$own_permission = self::definePermission('add_own_department_selfserve_vehicle_conditions', subusers_permission_node_key::SELFSERVE_ADD);
@@ -311,6 +318,7 @@ class departmentSelfserveVehicleConditionsRoute
* Update a department self-serve vehicle condition
*/
$this->put('/department/selfserve/vehicle/conditions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/vehicle/conditions');
global $response;
$user = (new authentication())->get_user();
if (!$user) {
@@ -408,6 +416,7 @@ class departmentSelfserveVehicleConditionsRoute
* Delete a department self-serve vehicle condition
*/
$this->delete('/department/selfserve/vehicle/conditions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/department/selfserve/vehicle/conditions');
global $response;
$user = (new authentication())->get_user();
if (!$user) {
@@ -12,6 +12,9 @@ use objects\logs_o;
use objects\product_options_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class departmentTimeBookingsRoute
{
use route_t;
@@ -25,6 +28,7 @@ class departmentTimeBookingsRoute
/** Department Time Bookings -> List */
$this->get('/department/timebookings/opening-hours', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/department/timebookings/opening-hours');
global $response;
$this->requirePermission('department_timebookings_opening_hours_get');
$user = (new authentication())->get_user();
@@ -74,6 +78,7 @@ class departmentTimeBookingsRoute
/** Department Time Bookings -> Update */
$this->put('/department/timebookings/opening-hours', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/department/timebookings/opening-hours');
global $response;
$this->requirePermission('department_timebookings_opening_hours_put');
$user = (new authentication())->get_user();
@@ -124,6 +129,7 @@ class departmentTimeBookingsRoute
/** Department Time Bookings -> Types */
$this->get('/department/timebookings/types', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/department/timebookings/types');
global $response;
$this->requirePermission('department_timebookings_types_get');
$user = (new authentication())->get_user();
@@ -169,6 +175,7 @@ class departmentTimeBookingsRoute
/** Department Time Bookings -> Types -> Add */
$this->post('/department/timebookings/types', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/department/timebookings/types');
global $response;
$this->requirePermission('department_timebookings_types_post');
$user = (new authentication())->get_user();
@@ -204,6 +211,7 @@ class departmentTimeBookingsRoute
/** Department Time Bookings -> Types -> Update */
$this->put('/department/timebookings/types', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/department/timebookings/types');
global $response;
$this->requirePermission('department_timebookings_types_put');
$user = (new authentication())->get_user();
@@ -239,6 +247,7 @@ class departmentTimeBookingsRoute
/** Department Time Bookings -> Types -> Delete */
$this->delete('/department/timebookings/types', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/department/timebookings/types');
global $response;
$this->requirePermission('department_timebookings_types_delete');
$user = (new authentication())->get_user();
@@ -269,6 +278,7 @@ class departmentTimeBookingsRoute
/** Department Time Bookings -> Entries */
$this->get('/department/timebookings/entries', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/department/timebookings/entries');
global $response;
$this->requirePermission('department_timebookings_entries_get');
$user = (new authentication())->get_user();
@@ -324,6 +334,7 @@ class departmentTimeBookingsRoute
/** Department Time Bookings -> Entries -> Add */
$this->post('/department/timebookings/entries', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/department/timebookings/entries');
global $response;
$this->requirePermission('department_timebookings_entries_post');
$user = (new authentication())->get_user();
@@ -16,6 +16,9 @@ use objects\logs_o;
use objects\orders_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class departmentsRoute
{
use route_t;
@@ -83,6 +86,7 @@ class departmentsRoute
public function run(): void
{
$this->get('/departments', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/departments');
// Require the user to be logged in
global $response;
$this->requirePermission('list_departments');
@@ -173,6 +177,7 @@ class departmentsRoute
);
$this->post('/departments', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/departments');
// Require the user to be logged in
global $response;
$this->requirePermission('add_department');
@@ -209,6 +214,7 @@ class departmentsRoute
);
$this->put('/departments', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/departments');
// Require the user to be logged in
global $response;
$this->requirePermission('edit_department');
@@ -265,6 +271,7 @@ class departmentsRoute
);
$this->get('/departments/categories', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/departments/categories');
// Require the user to be logged in
global $response;
$auth = new authentication();
@@ -323,6 +330,7 @@ class departmentsRoute
);
$this->get('/departments/self-serve/enabled', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/departments/self-serve/enabled');
// Require the user to be logged in
global $response;
$this->requirePermission('view_department_selfserve_enabled');
@@ -362,6 +370,7 @@ class departmentsRoute
);
$this->put('/departments/self-serve/enabled', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/departments/self-serve/enabled');
// Require the user to be logged in
global $response;
$this->requirePermission('edit_department_selfserve_enabled');
@@ -413,6 +422,7 @@ class departmentsRoute
);
$this->post('/departments/categories', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/departments/categories');
// Require the user to be logged in
global $response;
$this->requirePermission('add_department_category');
@@ -465,6 +475,7 @@ class departmentsRoute
);
$this->delete('/departments/categories', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/departments/categories');
// Require the user to be logged in
global $response;
$this->requirePermission('delete_department_category');
@@ -15,6 +15,9 @@ use objects\orders_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class economicInvoiceRoute
{
use route_t;
@@ -26,6 +29,7 @@ class economicInvoiceRoute
$router, $response;
$this->post('/economic/invoice/draft/export', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/economic/invoice/draft/export');
global $response;
$this->requirePermission('economic_invoice_draft_export');
$user = (new authentication())->get_user();
@@ -99,6 +103,7 @@ class economicInvoiceRoute
]);
$this->delete('/economic/invoice/draft/delete', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/economic/invoice/draft/delete');
global /** @var response $response */
$response;
$this->requirePermission('economic_invoice_draft_delete');
@@ -139,6 +144,7 @@ class economicInvoiceRoute
]);
$this->post('/economic/invoice/export', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/economic/invoice/export');
global $response;
$this->requirePermission('economic_invoice_export');
$user = (new authentication())->get_user();
@@ -223,6 +229,7 @@ class economicInvoiceRoute
]);
$this->get('/economic/invoice/draft/export/status', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/economic/invoice/draft/export/status');
global $response;
$this->requirePermission('economic_invoice_draft_export');
$user = (new authentication())->get_user();
@@ -248,6 +255,7 @@ class economicInvoiceRoute
]);
$this->post('/economic/invoice/draft/export/retry', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/economic/invoice/draft/export/retry');
global $response;
$this->requirePermission('economic_invoice_draft_export');
$user = (new authentication())->get_user();
@@ -282,6 +290,7 @@ class economicInvoiceRoute
]);
$this->get('/economic/invoice/export/status', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/economic/invoice/export/status');
global $response;
$this->requirePermission('economic_invoice_export');
$user = (new authentication())->get_user();
@@ -307,6 +316,7 @@ class economicInvoiceRoute
]);
$this->post('/economic/invoice/export/retry', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/economic/invoice/export/retry');
global $response;
$this->requirePermission('economic_invoice_export');
$user = (new authentication())->get_user();
@@ -9,6 +9,9 @@ use classes\router;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class economicLayoutsRoute
{
use route_t;
@@ -21,6 +24,7 @@ class economicLayoutsRoute
$this->get('/economic/layouts', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/economic/layouts');
global $response;
$this->requirePermission('economic_layouts');
$user = (new authentication())->get_user();
@@ -9,6 +9,9 @@ use classes\router;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class economicPaymentTermsRoute
{
use route_t;
@@ -21,6 +24,7 @@ class economicPaymentTermsRoute
$this->get('/economic/payment-terms', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/economic/payment-terms');
global $response;
$this->requirePermission('economic_payment_terms');
$user = (new authentication())->get_user();
@@ -13,6 +13,8 @@ use objects\departments_o;
use objects\order_items_o;
use objects\orders_o;
use objects\products_o;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
use objects\users_o;
use traits\route_t;
@@ -23,6 +25,7 @@ class exampleRoute
public function run(): void
{
$this->get('/example', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/example');
global $response;
$response->success(['message' => 'Hello World!']);
});
@@ -7,6 +7,9 @@ use objects\logs_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class intimidateRoute
{
use route_t;
@@ -14,6 +17,7 @@ class intimidateRoute
public function run(): void
{
$this->post('/su/intimidate', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/su/intimidate');
// Get the post data
global $response;
// Make sure the user has the SUPERUSER_INTIMIDATE permission
@@ -12,6 +12,9 @@ use objects\orders_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class invoicesRoute
{
use route_t;
@@ -19,6 +22,7 @@ class invoicesRoute
public function run(): void
{
$this->get('/invoices/draft', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/invoices/draft');
// Require the user to be logged in
global $response;
$this->requirePermission('get_invoice_draft');
@@ -57,6 +61,7 @@ class invoicesRoute
);
$this->post('/invoices/draft/close', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/invoices/draft/close');
// Require the user to be logged in
global $response;
$this->requirePermission('close_invoice_draft');
@@ -94,6 +99,7 @@ class invoicesRoute
);
$this->get('/invoices/pdf', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/invoices/pdf');
// Require the user to be logged in
global $response;
$this->requirePermission('get_invoice_pdf');
@@ -8,6 +8,9 @@ use classes\limited_backoffice_login_grant_service;
use classes\limited_backoffice_service;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
require_once WD . '/classes/limited_backoffice_login_grant_service.php';
class limitedBackofficeRoute
@@ -17,6 +20,7 @@ class limitedBackofficeRoute
public function run(): void
{
$this->get('/limited-backoffice/departments', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/limited-backoffice/departments');
$this->withLimitedBackoffice(function (limited_backoffice_service $service, $user): array {
$this->requirePermission(limited_backoffice_service::PERMISSION_ACCESS);
return $service->departmentsForUser($user);
@@ -11,6 +11,9 @@ use objects\logs_o;
use objects\plate_scanners_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class machineButtonPressRoute
{
use route_t;
@@ -18,6 +21,7 @@ class machineButtonPressRoute
public function run(): void
{
$handler = function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/relay/button/press/post');
global $response;
self::requirePlateScannerAuth();
@@ -7,6 +7,9 @@ use objects\logs_o;
use objects\module_action_logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleActionLogsRoute
{
use route_t;
@@ -15,6 +18,7 @@ class moduleActionLogsRoute
{
/** Modules > Action Logs > List */
$this->get('/modules/action-logs', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/action-logs');
global $response;
$this->requirePermission('modules_action_logs_view');
@@ -10,6 +10,9 @@ use objects\logs_o;
use Throwable;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleBackupsRoute
{
use route_t;
@@ -21,6 +24,7 @@ class moduleBackupsRoute
$router, $response;
$this->get('/modules/backup/backups', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/backup/backups');
global $response;
$this->requireClassicSuperuserPermission('modules_backup_list');
try {
@@ -38,6 +42,7 @@ class moduleBackupsRoute
]);
$this->post('/modules/backup/backups', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/backup/backups');
global $response;
$this->requireClassicSuperuserPermission('modules_backup_create');
$user_id = $this->actorUserId();
@@ -59,6 +64,7 @@ class moduleBackupsRoute
]);
$this->get('/modules/backup/jobs/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/backup/jobs/{id}');
global $response;
$this->requireClassicSuperuserPermission('modules_backup_list');
$job_id = (int)$this->fromRoute('id');
@@ -72,6 +78,7 @@ class moduleBackupsRoute
]);
$this->post('/modules/backup/backups/{backup_uuid}/verify', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/backup/backups/{backup_uuid}/verify');
global $response;
$this->requireClassicSuperuserPermission('modules_backup_verify');
try {
@@ -87,6 +94,7 @@ class moduleBackupsRoute
]);
$this->post('/modules/backup/backups/{backup_uuid}/restore/preview', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/backup/backups/{backup_uuid}/restore/preview');
global $response;
$this->requireClassicSuperuserPermission('modules_backup_restore');
try {
@@ -102,6 +110,7 @@ class moduleBackupsRoute
]);
$this->post('/modules/backup/backups/{backup_uuid}/restore', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/backup/backups/{backup_uuid}/restore');
global $response;
$this->requireClassicSuperuserPermission('modules_backup_restore');
try {
@@ -128,6 +137,7 @@ class moduleBackupsRoute
]);
$this->get('/modules/backup/restore-audit', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/backup/restore-audit');
global $response;
$this->requireClassicSuperuserPermission('modules_backup_restore');
try {
@@ -19,6 +19,9 @@ use classes\workfeed;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleConfigRoute
{
use route_t;
@@ -32,6 +35,7 @@ class moduleConfigRoute
/** Economic config > GET */
$this->get('/economic/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/economic/config');
global $response;
$this->requirePermission('economic_config');
$user = (new authentication())->get_user();
@@ -52,6 +56,7 @@ class moduleConfigRoute
/** Economic config > POST */
$this->post('/economic/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/economic/config');
global $response;
$this->requirePermission('economic_config');
$user = (new authentication())->get_user();
@@ -72,6 +77,7 @@ class moduleConfigRoute
/** reCAPTCHA config > GET */
$this->get('/reCAPTCHA/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/reCAPTCHA/config');
global $response;
$this->requirePermission('recaptcha_config');
$user = (new authentication())->get_user();
@@ -92,6 +98,7 @@ class moduleConfigRoute
/** reCAPTCHA config > POST */
$this->post('/reCAPTCHA/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/reCAPTCHA/config');
global $response;
$this->requirePermission('recaptcha_config');
$user = (new authentication())->get_user();
@@ -112,6 +119,7 @@ class moduleConfigRoute
/** Email config > GET */
$this->get('/email/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/email/config');
global $response;
$this->requirePermission('email_config');
$user = (new authentication())->get_user();
@@ -132,6 +140,7 @@ class moduleConfigRoute
/** Email config > POST */
$this->post('/email/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/email/config');
global $response;
$this->requirePermission('email_config');
$user = (new authentication())->get_user();
@@ -152,6 +161,7 @@ class moduleConfigRoute
/** Email config > TEST */
$this->post('/email/config/test', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/email/config/test');
global $response;
$this->requirePermission('email_config');
$user = (new authentication())->get_user();
@@ -183,6 +193,7 @@ class moduleConfigRoute
/** Slack config > GET */
$this->get('/slack/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/slack/config');
global $response;
$this->requirePermission('slack_config');
$user = (new authentication())->get_user();
@@ -203,6 +214,7 @@ class moduleConfigRoute
/** Slack config > POST */
$this->post('/slack/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/slack/config');
global $response;
$this->requirePermission('slack_config');
$user = (new authentication())->get_user();
@@ -223,6 +235,7 @@ class moduleConfigRoute
/** Slack config > TEST */
$this->post('/slack/config/test', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/slack/config/test');
global $response;
$this->requirePermission('slack_config');
$user = (new authentication())->get_user();
@@ -252,6 +265,7 @@ class moduleConfigRoute
/** Slack internal department goal progress config > TEST */
$this->post('/slack/config/internal-department-goal-progress/test', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/slack/config/internal-department-goal-progress/test');
global $response;
$this->requirePermission('slack_config');
$user = (new authentication())->get_user();
@@ -281,6 +295,7 @@ class moduleConfigRoute
/** Slack internal department goal progress config > GET */
$this->get('/slack/config/internal-department-goal-progress', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/slack/config/internal-department-goal-progress');
global $response;
$this->requirePermission('slack_config');
$user = (new authentication())->get_user();
@@ -301,6 +316,7 @@ class moduleConfigRoute
/** Slack internal department goal progress config > POST */
$this->post('/slack/config/internal-department-goal-progress', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/slack/config/internal-department-goal-progress');
global $response;
$this->requirePermission('slack_config');
$user = (new authentication())->get_user();
@@ -334,6 +350,7 @@ class moduleConfigRoute
);
$this->get('/backups/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/backups/config');
global $response;
$this->requirePermission('backups_config');
$user = (new authentication())->get_user();
@@ -353,6 +370,7 @@ class moduleConfigRoute
);
$this->post('/backups/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/backups/config');
global $response;
$this->requirePermission('backups_config');
$user = (new authentication())->get_user();
@@ -372,6 +390,7 @@ class moduleConfigRoute
);
$this->get('/failover/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/failover/config');
global $response;
$this->requirePermission('modules_failover_config');
$user = (new authentication())->get_user();
@@ -391,6 +410,7 @@ class moduleConfigRoute
);
$this->post('/failover/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/failover/config');
global $response;
$this->requirePermission('modules_failover_config');
$user = (new authentication())->get_user();
@@ -410,6 +430,7 @@ class moduleConfigRoute
);
$this->get('/coolify/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/coolify/config');
global $response;
$this->requirePermission('superuser_coolify_manage');
$user = (new authentication())->get_user();
@@ -429,6 +450,7 @@ class moduleConfigRoute
);
$this->post('/coolify/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/coolify/config');
global $response;
$this->requirePermission('superuser_coolify_manage');
$user = (new authentication())->get_user();
@@ -449,6 +471,7 @@ class moduleConfigRoute
/** Bird config > GET */
$this->get('/bird/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/bird/config');
global $response;
$this->requirePermission('modules_bird_config');
$user = (new authentication())->get_user();
@@ -469,6 +492,7 @@ class moduleConfigRoute
/** Bird config > POST */
$this->post('/bird/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/bird/config');
global $response;
$this->requirePermission('modules_bird_config');
$user = (new authentication())->get_user();
@@ -489,6 +513,7 @@ class moduleConfigRoute
/** MotorAPI config > GET */
$this->get('/motorapi/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/motorapi/config');
global $response;
$this->requirePermission('motorapi_config');
$user = (new authentication())->get_user();
@@ -509,6 +534,7 @@ class moduleConfigRoute
/** MotorAPI config > POST */
$this->post('/motorapi/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/motorapi/config');
global $response;
$this->requirePermission('motorapi_config');
$user = (new authentication())->get_user();
@@ -529,6 +555,7 @@ class moduleConfigRoute
/** Stripe config > GET */
$this->get('/stripe/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/stripe/config');
global $response;
$this->requirePermission('stripe_config');
$user = (new authentication())->get_user();
@@ -549,6 +576,7 @@ class moduleConfigRoute
/** Stripe config > POST */
$this->post('/stripe/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/stripe/config');
global $response;
$this->requirePermission('stripe_config');
$user = (new authentication())->get_user();
@@ -569,6 +597,7 @@ class moduleConfigRoute
/** FXRatesAPI config > GET */
$this->get('/fxratesapi/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/fxratesapi/config');
global $response;
$this->requirePermission('fxratesapi_config');
$user = (new authentication())->get_user();
@@ -588,6 +617,7 @@ class moduleConfigRoute
);
/** FXRatesAPI config > POST */
$this->post('/fxratesapi/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/fxratesapi/config');
global $response;
$this->requirePermission('fxratesapi_config');
$user = (new authentication())->get_user();
@@ -607,6 +637,7 @@ class moduleConfigRoute
);
/** GatewayAPI config > GET */
$this->get('/gatewayapi/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/gatewayapi/config');
global $response;
$this->requirePermission('gatewayapi_config');
$user = (new authentication())->get_user();
@@ -626,6 +657,7 @@ class moduleConfigRoute
);
/** GatewayAPI config > POST */
$this->post('/gatewayapi/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/gatewayapi/config');
global $response;
$this->requirePermission('gatewayapi_config');
$user = (new authentication())->get_user();
@@ -646,6 +678,7 @@ class moduleConfigRoute
/** WeatherAPI config > GET */
$this->get('/weatherapi/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/weatherapi/config');
global $response;
$this->requirePermission('weatherapi_config');
$user = (new authentication())->get_user();
@@ -665,6 +698,7 @@ class moduleConfigRoute
);
/** WeatherAPI config > POST */
$this->post('/weatherapi/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/weatherapi/config');
global $response;
$this->requirePermission('weatherapi_config');
$user = (new authentication())->get_user();
@@ -685,6 +719,7 @@ class moduleConfigRoute
/** n8n config > GET */
$this->get('/n8n/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/n8n/config');
global $response;
$this->requirePermission('modules_n8n_config');
$user = (new authentication())->get_user();
@@ -704,6 +739,7 @@ class moduleConfigRoute
);
/** n8n config > POST */
$this->post('/n8n/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/n8n/config');
global $response;
$this->requirePermission('modules_n8n_config');
$user = (new authentication())->get_user();
@@ -724,6 +760,7 @@ class moduleConfigRoute
/** Workfeed config > GET */
$this->get('/workfeed/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/workfeed/config');
global $response;
$this->requirePermission('modules_workfeed_config');
$user = (new authentication())->get_user();
@@ -743,6 +780,7 @@ class moduleConfigRoute
);
/** Workfeed config > POST */
$this->post('/workfeed/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/workfeed/config');
global $response;
$this->requirePermission('modules_workfeed_config');
$user = (new authentication())->get_user();
@@ -763,6 +801,7 @@ class moduleConfigRoute
/** XLVask config > GET */
$this->get('/xlvask/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/xlvask/config');
global $response;
$this->requirePermission('xlvask_config');
$user = (new authentication())->get_user();
@@ -782,6 +821,7 @@ class moduleConfigRoute
);
/** XLVask config > POST */
$this->post('/xlvask/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/xlvask/config');
global $response;
$this->requirePermission('xlvask_config');
$user = (new authentication())->get_user();
@@ -802,6 +842,7 @@ class moduleConfigRoute
/** Entra config > GET */
$this->get('/entra/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/entra/config');
global $response;
$this->requirePermission('entra_config');
$user = (new authentication())->get_user();
@@ -821,6 +862,7 @@ class moduleConfigRoute
);
/** Entra config > POST */
$this->post('/entra/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/entra/config');
global $response;
$this->requirePermission('entra_config');
$user = (new authentication())->get_user();
@@ -840,6 +882,7 @@ class moduleConfigRoute
);
/** Limble config > GET */
$this->get('/limble/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/limble/config');
global $response;
$this->requirePermission('modules_limble_config');
$user = (new authentication())->get_user();
@@ -859,6 +902,7 @@ class moduleConfigRoute
);
/** Limble config > POST */
$this->post('/limble/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/limble/config');
global $response;
$this->requirePermission('modules_limble_config');
$user = (new authentication())->get_user();
@@ -878,6 +922,7 @@ class moduleConfigRoute
);
/** OcrSpace config > GET */
$this->get('/ocrspace/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/ocrspace/config');
global $response;
$this->requirePermission('modules_ocrspace_config');
$user = (new authentication())->get_user();
@@ -897,6 +942,7 @@ class moduleConfigRoute
);
/** OcrSpace config > POST */
$this->post('/ocrspace/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/ocrspace/config');
global $response;
$this->requirePermission('modules_ocrspace_config');
$user = (new authentication())->get_user();
@@ -916,6 +962,7 @@ class moduleConfigRoute
);
/** OpenAI config > GET */
$this->get('/openai/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/openai/config');
global $response;
$this->requirePermission('modules_openai_config');
$user = (new authentication())->get_user();
@@ -935,6 +982,7 @@ class moduleConfigRoute
);
/** OpenAI config > POST */
$this->post('/openai/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/openai/config');
global $response;
$this->requirePermission('modules_openai_config');
$user = (new authentication())->get_user();
@@ -954,6 +1002,7 @@ class moduleConfigRoute
);
/** LicensePlateRecognizer config > GET */
$this->get('/licenseplaterecognizer/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/licenseplaterecognizer/config');
global $response;
$this->requirePermission('modules_licenseplaterecognizer_config');
$user = (new authentication())->get_user();
@@ -973,6 +1022,7 @@ class moduleConfigRoute
);
/** LicensePlateRecognizer config > POST */
$this->post('/licenseplaterecognizer/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/licenseplaterecognizer/config');
global $response;
$this->requirePermission('modules_licenseplaterecognizer_config');
$user = (new authentication())->get_user();
@@ -992,6 +1042,7 @@ class moduleConfigRoute
);
/** Virkdata config > GET */
$this->get('/virkdata/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/virkdata/config');
global $response;
$this->requirePermission('modules_virkdata_config');
$user = (new authentication())->get_user();
@@ -1010,6 +1061,7 @@ class moduleConfigRoute
);
/** Virkdata config > POST */
$this->post('/virkdata/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/virkdata/config');
global $response;
$this->requirePermission('modules_virkdata_config');
$user = (new authentication())->get_user();
@@ -1029,6 +1081,7 @@ class moduleConfigRoute
);
/** Shelly config -> GET */
$this->get('/shelly/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/shelly/config');
global $response;
$this->requirePermission('modules_shelly_config');
$user = (new authentication())->get_user();
@@ -1046,6 +1099,7 @@ class moduleConfigRoute
]
);
$this->post('/shelly/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/shelly/config');
global $response;
$this->requirePermission('modules_shelly_config');
$user = (new authentication())->get_user();
@@ -1060,6 +1114,7 @@ class moduleConfigRoute
});
/** Self-Serve config -> GET */
$this->get('/selfserve/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/selfserve/config');
global $response;
$this->requirePermission('modules_selfserve_config');
$user = (new authentication())->get_user();
@@ -1077,6 +1132,7 @@ class moduleConfigRoute
]
);
$this->post('/selfserve/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/selfserve/config');
global $response;
$this->requirePermission('modules_selfserve_config');
$user = (new authentication())->get_user();
@@ -9,6 +9,9 @@ use classes\router;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleEconomicCustomerRoute
{
use route_t;
@@ -22,6 +25,7 @@ class moduleEconomicCustomerRoute
/** Modules > Economic > Customer > Get customer */
$this->get('/modules/economic/customer', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/modules/economic/customer');
global $response;
$this->requirePermission('modules_economic_customer_get');
$user = (new authentication())->get_user();
@@ -45,6 +49,7 @@ class moduleEconomicCustomerRoute
/** Modules > Economic > Customer > Create customer */
$this->post('/modules/economic/customer', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/modules/economic/customer');
global $response;
$this->requirePermission('modules_economic_customer_create');
$user = (new authentication())->get_user();
@@ -11,6 +11,9 @@ use objects\logs_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleEconomicRoute
{
use route_t;
@@ -24,6 +27,7 @@ class moduleEconomicRoute
/** Economic > Customers > Import customer */
$this->post('/economic/customers/import', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/economic/customers/import');
global $response;
$this->requirePermission('economic_import_customer');
$user = (new authentication())->get_user();
@@ -8,6 +8,9 @@ use classes\router;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleEntraRoute
{
use route_t;
@@ -21,6 +24,7 @@ class moduleEntraRoute
/** Modules > Entra > Users > GET */
$this->get('/modules/entra/users', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/entra/users');
global $response;
$this->requirePermission('modules_entra_users');
$user = (new authentication())->get_user();
@@ -9,6 +9,8 @@ use classes\router;
use objects\currency_conversion_rates_o;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleFxRatesAPIRoute
{
@@ -23,6 +25,7 @@ class moduleFxRatesAPIRoute
/** Modules > FXRatesAPI > conversion rate > GET */
$this->get('/modules/fxratesapi/rate', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/fxratesapi/rate');
global $response;
$this->requirePermission('modules_fxratesapi_rate');
$user = (new authentication())->get_user();
@@ -10,6 +10,9 @@ use limble\helpers\limble_tasks_pagination;
use limble\helpers\limble_webhook_payload_task;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleLimbleRoute
{
use route_t;
@@ -20,6 +23,7 @@ class moduleLimbleRoute
/** @var router $router */
$router, $response;
$this->post('/modules/limble/webhook/task', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/limble/webhook/task');
global $response;
$slack = new slack();
$this->requirePermission('modules_limble_webhooks_task');
@@ -41,6 +45,7 @@ class moduleLimbleRoute
);
$this->get('/modules/limble/tasks', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/limble/tasks');
global $response;
$slack = new slack();
$slack->send_message('Limble Tasks Endpoint Triggered', 'Limble Tasks');
@@ -9,6 +9,9 @@ use classes\router;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleMotorAPIRoute
{
use route_t;
@@ -22,6 +25,7 @@ class moduleMotorAPIRoute
/** Modules > MotorAPI > Lookup > GET */
$this->get('/modules/motorapi/lookup', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/motorapi/lookup');
global $response;
$this->requirePermission('modules_motorapi_lookup');
$user = (new authentication())->get_user();
@@ -10,6 +10,9 @@ use objects\logs_o;
use stdClass;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleN8nRoute
{
use route_t;
@@ -21,6 +24,7 @@ class moduleN8nRoute
$router, $response;
$this->get('/modules/n8n/workflows', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/n8n/workflows');
global $response;
$this->requirePermission('modules_n8n_workflows_view');
$user = (new authentication())->get_user();
@@ -46,6 +50,7 @@ class moduleN8nRoute
]);
$this->get('/modules/n8n/workflows/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/n8n/workflows/{id}');
global $response;
$this->requirePermission('modules_n8n_workflows_view');
$user = (new authentication())->get_user();
@@ -62,6 +67,7 @@ class moduleN8nRoute
]);
$this->post('/modules/n8n/workflows', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/n8n/workflows');
global $response;
$this->requirePermission('modules_n8n_workflows_manage');
$user = (new authentication())->get_user();
@@ -80,6 +86,7 @@ class moduleN8nRoute
]);
$this->put('/modules/n8n/workflows/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/n8n/workflows/{id}');
global $response;
$this->requirePermission('modules_n8n_workflows_manage');
$user = (new authentication())->get_user();
@@ -98,6 +105,7 @@ class moduleN8nRoute
]);
$this->post('/modules/n8n/workflows/{id}/publish', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/n8n/workflows/{id}/publish');
global $response;
$this->requirePermission('modules_n8n_workflows_manage');
$user = (new authentication())->get_user();
@@ -116,6 +124,7 @@ class moduleN8nRoute
]);
$this->post('/modules/n8n/workflows/{id}/deactivate', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/n8n/workflows/{id}/deactivate');
global $response;
$this->requirePermission('modules_n8n_workflows_manage');
$user = (new authentication())->get_user();
@@ -131,6 +140,7 @@ class moduleN8nRoute
]);
$this->post('/modules/n8n/webhooks/trigger', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/n8n/webhooks/trigger');
global $response;
$this->requirePermission('modules_n8n_workflows_run');
$user = (new authentication())->get_user();
@@ -152,6 +162,7 @@ class moduleN8nRoute
]);
$this->get('/modules/n8n/executions', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/n8n/executions');
global $response;
$this->requirePermission('modules_n8n_executions_view');
$user = (new authentication())->get_user();
@@ -176,6 +187,7 @@ class moduleN8nRoute
]);
$this->get('/modules/n8n/executions/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/n8n/executions/{id}');
global $response;
$this->requirePermission('modules_n8n_executions_view');
$user = (new authentication())->get_user();
@@ -191,6 +203,7 @@ class moduleN8nRoute
]);
$this->post('/modules/n8n/executions/{id}/retry', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/n8n/executions/{id}/retry');
global $response;
$this->requirePermission('modules_n8n_workflows_run');
$user = (new authentication())->get_user();
@@ -211,6 +224,7 @@ class moduleN8nRoute
]);
$this->post('/modules/n8n/executions/{id}/stop', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/n8n/executions/{id}/stop');
global $response;
$this->requirePermission('modules_n8n_workflows_manage');
$user = (new authentication())->get_user();
@@ -6,6 +6,9 @@ use classes\licenseplaterecognizer;
use classes\response;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleScannerRoute
{
use route_t;
@@ -37,6 +40,7 @@ class moduleScannerRoute
$router, $response;
/** Modules > Scanner > License Plate Recognition > POST */
$this->post('/modules/scanner/lpr', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/scanner/lpr');
global $response;
$route_started_at = microtime(true);
$image_upload = self::getLPRImageUpload();
@@ -33,6 +33,9 @@ use objects\subusers_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleSelfServeRoute
{
use route_t;
@@ -50,6 +53,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Status */
$this->get('/modules/self-serve/lane/status', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/self-serve/lane/status');
global $response;
$this->requirePermission('modules_selfserve_lane_status_view');
$selfserve = new selfserve();
@@ -72,6 +76,7 @@ class moduleSelfServeRoute
);
$this->put('/modules/self-serve/lane/status', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/status');
global $response;
$this->requirePermission('modules_selfserve_lane_status_set');
@@ -127,6 +132,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Wash > In-progress details */
$this->get('/modules/self-serve/lane/wash/in-progress', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/self-serve/lane/wash/in-progress');
global $response;
self::requireParameters(['lane_id']);
$lane_id = (int)$this->getParameter('lane_id');
@@ -347,6 +353,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Wash > My active wash */
$this->get('/modules/self-serve/lane/wash/my-active-wash', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/self-serve/lane/wash/my-active-wash');
global $response;
$principal_scope = $this->requireMyActiveWashPrincipalScope();
@@ -367,6 +374,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Sessions */
$this->get('/modules/self-serve/sessions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/self-serve/sessions');
global $response;
$this->requirePermission('modules_selfserve_sessions_view');
@@ -420,6 +428,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Session detail */
$this->get('/modules/self-serve/sessions/{id}', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/self-serve/sessions/{id}');
global $response;
$this->requirePermission('modules_selfserve_sessions_view');
$session_id = (int)$this->fromRoute('id');
@@ -439,6 +448,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Force > Stop */
$this->post('/modules/self-serve/lane/force/stop', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/force/stop');
global $response;
$this->requirePermission('modules_selfserve_sessions_force_stop');
self::requireParameters(['lane_id', 'bill']);
@@ -480,6 +490,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Command */
$this->post('/modules/self-serve/lane/command', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/command');
global $response;
$selfserve = new selfserve();
// Get the request user
@@ -649,6 +660,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Allowed services (derived from shown tasks) */
$this->post('/modules/self-serve/lane/services/allowed', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/services/allowed');
global $response;
$selfserve = new selfserve();
// Validate parameters
@@ -756,6 +768,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Gate > Open (ENTRANCE/EXIT) */
$this->post('/modules/self-serve/lane/gate/open', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/gate/open');
global $response;
$this->requirePermission('modules_selfserve_lane_gate_open');
$selfserve = new selfserve();
@@ -805,6 +818,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Hardware > Batch status */
$this->post('/modules/self-serve/lane/hardware/batch/status', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/hardware/batch/status');
global $response;
$selfserve = new selfserve();
self::requireParameters(['lane_id']);
@@ -840,6 +854,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Hardware > Batch set/open */
$this->post('/modules/self-serve/lane/hardware/batch/set', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/hardware/batch/set');
global $response;
$selfserve = new selfserve();
self::requireParameters(['lane_id', 'commands']);
@@ -869,6 +884,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Hardware > Batch poll */
$this->get('/modules/self-serve/lane/hardware/batch/{batch_id}', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/self-serve/lane/hardware/batch/{batch_id}');
global $response;
$this->requirePermission('modules_selfserve_lane_relay_machine_status_view');
try {
@@ -882,6 +898,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Relay > MACHINE_PROGRAM_PICKER status */
$this->get('/modules/self-serve/lane/relay/machine_program_picker/status', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/self-serve/lane/relay/machine_program_picker/status');
global $response;
$this->requirePermission('modules_selfserve_lane_relay_machine_program_picker_status_view');
$selfserve = new selfserve();
@@ -904,6 +921,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Relay > MACHINE_PROGRAM_PICKER set on/off */
$this->post('/modules/self-serve/lane/relay/machine_program_picker/set', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/relay/machine_program_picker/set');
global $response;
$this->requirePermission('modules_selfserve_lane_relay_machine_program_picker_status_set');
$selfserve = new selfserve();
@@ -935,6 +953,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Relay > MACHINE_CLEANER status */
$this->get('/modules/self-serve/lane/relay/machine_cleaner/status', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/self-serve/lane/relay/machine_cleaner/status');
global $response;
$this->requirePermission('modules_selfserve_lane_relay_machine_cleaner_status_view');
$selfserve = new selfserve();
@@ -957,6 +976,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Relay > MACHINE_CLEANER set on/off */
$this->post('/modules/self-serve/lane/relay/machine_cleaner/set', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/relay/machine_cleaner/set');
global $response;
$this->requirePermission('modules_selfserve_lane_relay_machine_cleaner_status_set');
$selfserve = new selfserve();
@@ -988,6 +1008,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Relay > MACHINE status */
$this->get('/modules/self-serve/lane/relay/machine/status', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/self-serve/lane/relay/machine/status');
global $response;
$this->requirePermission('modules_selfserve_lane_relay_machine_status_view');
$selfserve = new selfserve();
@@ -1010,6 +1031,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Relay > MACHINE set on/off */
$this->post('/modules/self-serve/lane/relay/machine/set', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/relay/machine/set');
global $response;
$this->requirePermission('modules_selfserve_lane_relay_machine_status_set');
$selfserve = new selfserve();
@@ -1058,6 +1080,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Relay > Enable MACHINE_PROGRAM_PICKER (manual) */
$this->post('/modules/self-serve/lane/relay/machine_program_picker/enable', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/relay/machine_program_picker/enable');
global $response;
$this->requirePermission('modules_selfserve_lane_relay_enable_machine_program_picker');
$selfserve = new selfserve();
@@ -1091,6 +1114,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Relay > Enable MACHINE_CLEANER (manual) */
$this->post('/modules/self-serve/lane/relay/machine_cleaner/enable', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/relay/machine_cleaner/enable');
global $response;
$this->requirePermission('modules_selfserve_lane_relay_enable_machine_cleaner');
$selfserve = new selfserve();
@@ -1124,6 +1148,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Relay > Enable MACHINE (manual, gated by allowed services) */
$this->post('/modules/self-serve/lane/relay/machine/enable', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/relay/machine/enable');
global $response;
$selfserve = new selfserve();
// Validate parameters
@@ -1173,6 +1198,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Force > MACHINE_PROGRAM_PICKER enable */
$this->post('/modules/self-serve/lane/force/machine_program_picker/enable', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/force/machine_program_picker/enable');
global $response;
$this->requirePermission('modules_selfserve_lane_force_machine_program_picker_enable');
$selfserve = new selfserve();
@@ -1206,6 +1232,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Force > MACHINE_PROGRAM_PICKER disable */
$this->post('/modules/self-serve/lane/force/machine_program_picker/disable', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/force/machine_program_picker/disable');
global $response;
$this->requirePermission('modules_selfserve_lane_force_machine_program_picker_disable');
$selfserve = new selfserve();
@@ -1233,6 +1260,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Force > MACHINE_CLEANER enable */
$this->post('/modules/self-serve/lane/force/machine_cleaner/enable', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/force/machine_cleaner/enable');
global $response;
$this->requirePermission('modules_selfserve_lane_force_machine_cleaner_enable');
$selfserve = new selfserve();
@@ -1266,6 +1294,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Force > MACHINE_CLEANER disable */
$this->post('/modules/self-serve/lane/force/machine_cleaner/disable', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/force/machine_cleaner/disable');
global $response;
$this->requirePermission('modules_selfserve_lane_force_machine_cleaner_disable');
$selfserve = new selfserve();
@@ -1293,6 +1322,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Force > MACHINE enable (simulate started wash) */
$this->post('/modules/self-serve/lane/force/machine/enable', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/force/machine/enable');
global $response;
$this->requirePermission('modules_selfserve_lane_force_machine_enable');
$selfserve = new selfserve();
@@ -1367,6 +1397,7 @@ class moduleSelfServeRoute
/** Modules > Self Serve > Lane > Force > MACHINE disable (simulate started wash without machine) */
$this->post('/modules/self-serve/lane/force/machine/disable', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/modules/self-serve/lane/force/machine/disable');
global $response;
$this->requirePermission('modules_selfserve_lane_force_machine_disable');
$selfserve = new selfserve();
@@ -11,6 +11,9 @@ use objects\logs_o;
use objects\orders_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleStripeRoute
{
use route_t;
@@ -24,6 +27,7 @@ class moduleStripeRoute
/** Modules > Stripe > Customers > List */
$this->get('/modules/stripe/customers', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/modules/stripe/customers');
global $response;
$this->requirePermission('modules_stripe_customers_list');
$user = (new authentication())->get_user();
@@ -43,6 +47,7 @@ class moduleStripeRoute
/** Modules > Stripe > Products > List */
$this->get('/modules/stripe/products', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/modules/stripe/products');
global $response;
$this->requirePermission('modules_stripe_products_list');
$user = (new authentication())->get_user();
@@ -62,6 +67,7 @@ class moduleStripeRoute
/** Modules > Stripe > Prices > List */
$this->get('/modules/stripe/prices', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/modules/stripe/prices');
global $response;
$this->requirePermission('modules_stripe_prices_list');
$user = (new authentication())->get_user();
@@ -81,6 +87,7 @@ class moduleStripeRoute
/** Modules > Stripe > Retired direct payment-link creation */
$this->post('/modules/stripe/invoice', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/modules/stripe/invoice');
global $response;
$this->requirePermission('modules_stripe_invoice_send');
$response->error([
@@ -95,6 +102,7 @@ class moduleStripeRoute
/** Modules > Stripe > Cancel Invoice */
$this->delete('/modules/stripe/invoice', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/modules/stripe/invoice');
global $response;
$this->requirePermission('modules_stripe_invoice_send');
$user = (new authentication())->get_user();
@@ -6,6 +6,9 @@ use classes\module_usage_service;
use Exception;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleUsageRoute
{
use route_t;
@@ -13,6 +16,7 @@ class moduleUsageRoute
public function run(): void
{
$this->get('/modules/usage/summary', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/usage/summary');
global $response;
$this->requirePermission('modules_usage_view');
@@ -27,6 +31,7 @@ class moduleUsageRoute
]);
$this->get('/modules/usage/{moduleKey}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/usage/{moduleKey}');
global $response;
$this->requirePermission('modules_usage_view');
@@ -41,6 +46,7 @@ class moduleUsageRoute
]);
$this->patch('/modules/quotas/{moduleKey}/{metricKey}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/quotas/{moduleKey}/{metricKey}');
global $response;
$this->requirePermission('modules_quotas_manage');
@@ -11,6 +11,9 @@ use objects\currency_conversion_rates_o;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleVirkDataRoute
{
use route_t;
@@ -24,6 +27,7 @@ class moduleVirkDataRoute
/** Modules > VirkData > search > GET */
$this->get('/modules/virkdata/search', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/virkdata/search');
global $response;
$this->requirePermission('modules_virkdata_search');
$user = (new authentication())->get_user();
@@ -19,6 +19,8 @@ use objects\departments_o;
use objects\logs_o;
use objects\orders_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleWeatherAPIRoute
{
@@ -46,6 +48,7 @@ class moduleWeatherAPIRoute
$router, $response;
$this->get('/modules/weatherapi/current', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/weatherapi/current');
global $response;
$this->requirePermission('modules_weatherapi_current');
$user = (new authentication())->get_user();
@@ -9,6 +9,9 @@ use classes\workfeed;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleWorkfeedRoute
{
use route_t;
@@ -20,6 +23,7 @@ class moduleWorkfeedRoute
$router, $response;
$this->get('/modules/workfeed/employees', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/workfeed/employees');
global $response;
$this->requirePermission('modules_workfeed_employees_view');
$user = (new authentication())->get_user();
@@ -35,6 +39,7 @@ class moduleWorkfeedRoute
]);
$this->get('/modules/workfeed/employees/{id}', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/workfeed/employees/{id}');
global $response;
$this->requirePermission('modules_workfeed_employees_view');
$user = (new authentication())->get_user();
@@ -50,6 +55,7 @@ class moduleWorkfeedRoute
]);
$this->get('/modules/workfeed/shifts', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/workfeed/shifts');
global $response;
$this->requirePermission('modules_workfeed_shifts_view');
$user = (new authentication())->get_user();
@@ -94,6 +100,7 @@ class moduleWorkfeedRoute
]);
$this->get('/modules/workfeed/shifts/{id}', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/workfeed/shifts/{id}');
global $response;
$this->requirePermission('modules_workfeed_shifts_view');
$user = (new authentication())->get_user();
@@ -109,6 +116,7 @@ class moduleWorkfeedRoute
]);
$this->get('/modules/workfeed/departments', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/workfeed/departments');
global $response;
$this->requirePermission('modules_workfeed_departments_view');
$user = (new authentication())->get_user();
@@ -10,6 +10,9 @@ use objects\orders_o;
use objects\xlvask_customers_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class moduleXLVaskRoute
{
use route_t;
@@ -20,6 +23,7 @@ class moduleXLVaskRoute
/** @var router $router */
$router, $response;
$this->get('/modules/xlvask/usageLog', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/xlvask/usageLog');
global $response;
$this->requirePermission('modules_xlvask_usageLog');
$params = [
@@ -48,6 +52,7 @@ class moduleXLVaskRoute
);
$this->get('/modules/xlvask/vehicles', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/xlvask/vehicles');
global $response;
$this->requirePermission('modules_xlvask_vehicles');
$params = [
@@ -74,6 +79,7 @@ class moduleXLVaskRoute
);
$this->get('/modules/xlvask/customers', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/xlvask/customers');
global $response;
$this->requirePermission('modules_xlvask_customers');
$params = [
@@ -102,6 +108,7 @@ class moduleXLVaskRoute
);
$this->get('/modules/xlvask/internal/vehicle-types', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/xlvask/internal/vehicle-types');
global $response;
$this->requirePermission('modules_xlvask_internal_vehicle_types');
$user = (new authentication())->get_user();
@@ -122,6 +129,7 @@ class moduleXLVaskRoute
);
$this->get('/modules/xlvask/related-orders', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/xlvask/related-orders');
global $response;
$this->requirePermission('modules_xlvask_related_orders');
self::requireParameters(['washIds']);
@@ -156,6 +164,7 @@ class moduleXLVaskRoute
);
$this->get('/modules/xlvask/tasks/sync-users', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/xlvask/tasks/sync-users');
global $response;
$this->requirePermission('modules_xlvask_sync_users');
// Create the xlvask tasks object
@@ -174,6 +183,7 @@ class moduleXLVaskRoute
);
$this->get('/modules/xlvask/tasks/sync-usage', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/xlvask/tasks/sync-usage');
global $response;
$this->requirePermission('modules_xlvask_sync_usage');
// Create the xlvask tasks object
@@ -192,6 +202,7 @@ class moduleXLVaskRoute
);
$this->get('/modules/xlvask/tasks/import-customers', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/xlvask/tasks/import-customers');
global $response;
$this->requirePermission('modules_xlvask_import_customers');
// Create the xlvask_customers_o object
@@ -208,6 +219,7 @@ class moduleXLVaskRoute
);
$this->get('/modules/xlvask/tasks/import-vehicles', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/xlvask/tasks/import-vehicles');
global $response;
$this->requirePermission('modules_xlvask_import_vehicles');
// Create the xlvask_vehicles_o object
@@ -7,6 +7,9 @@ use objects\logs_o;
use objects\notifications_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class notificationsRoute
{
use route_t;
@@ -14,6 +17,7 @@ class notificationsRoute
public function run(): void
{
$this->get('/notifications', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/notifications');
// Require the user to be logged in
global $response;
$this->requirePermission('list_notifications');
@@ -77,6 +81,7 @@ class notificationsRoute
);
$this->post('/notifications', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/notifications');
// Require the user to be logged in
global $response;
$this->requirePermission('add_notification');
@@ -130,6 +135,7 @@ class notificationsRoute
$this->delete('/notifications', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/notifications');
// Require the user to be logged in
global $response;
$this->requirePermission('delete_own_notifications');
@@ -20,6 +20,9 @@ use objects\products_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
require_once WD . '/classes/security_policy_service.php';
class orderBookingRoute
@@ -29,6 +32,7 @@ class orderBookingRoute
public function run(): void
{
$this->post('/order-bookings', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/order-bookings');
// Require the user to be logged in
global $response;
/**
@@ -106,6 +110,7 @@ class orderBookingRoute
);
$this->get('/order-bookings', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/order-bookings');
// Require the user to be logged in
global $response;
/**
@@ -183,6 +188,7 @@ class orderBookingRoute
);
$this->get('/order-bookings/counts', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/order-bookings/counts');
global $response;
$auth = new authentication();
@@ -254,6 +260,7 @@ class orderBookingRoute
);
$this->put('/order-bookings', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/order-bookings');
// Require the user to be logged in
global $response;
/**
@@ -337,6 +344,7 @@ class orderBookingRoute
);
$this->delete('/order-bookings', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/order-bookings');
// Require the user to be logged in
global $response;
/**
@@ -378,6 +386,7 @@ class orderBookingRoute
);
$this->post('/order-bookings/booking-confirmation/resend', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/order-bookings/booking-confirmation/resend');
global $response;
$object = self::getTargetObject();
@@ -401,6 +410,7 @@ class orderBookingRoute
);
$this->post('/order-bookings/completion-confirmation/resend', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/order-bookings/completion-confirmation/resend');
global $response;
$object = self::getTargetObject();
@@ -432,6 +442,7 @@ class orderBookingRoute
);
$this->post('/order-bookings/complete', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/order-bookings/complete');
// Require the user to be logged in
global $response;
/**
@@ -25,6 +25,9 @@ use objects\orders_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class orderInvoicesRoute
{
use route_t;
@@ -37,6 +40,7 @@ class orderInvoicesRoute
/** Collected order invoices > GET */
$this->get('/collected-invoices', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/collected-invoices');
global $response;
$this->requirePermission('list_collected_invoices');
$user = (new authentication())->get_user();
@@ -142,6 +146,7 @@ class orderInvoicesRoute
/** Collected order invoices > Compare with E-conomic > GET */
$this->get('/collected-invoices/economic/compare', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/collected-invoices/economic/compare');
global $response;
$this->requirePermission('compare_collected_invoice_economic');
//$user = (new authentication())->get_user();
@@ -241,6 +246,7 @@ class orderInvoicesRoute
/** Collected order invoices > E-conomic V2 details > GET */
$this->get('/collected-invoices/economic/v2/details', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/collected-invoices/economic/v2/details');
global $response;
$this->requirePermission('view_collected_invoice_economic_v2_details');
$collected_invoice_id = $this->requireCollectedInvoiceId();
@@ -255,6 +261,7 @@ class orderInvoicesRoute
/** Collected order invoices > E-conomic PDF > GET */
$this->get('/collected-invoices/economic/pdf', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/collected-invoices/economic/pdf');
global $response;
$this->requirePermission('download_collected_invoice_economic_pdf');
$collected_invoice_id = $this->requireCollectedInvoiceId();
@@ -275,6 +282,7 @@ class orderInvoicesRoute
/** Collected order invoices > E-conomic V2 compare > GET */
$this->get('/collected-invoices/economic/v2/compare', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/collected-invoices/economic/v2/compare');
global $response;
$this->requirePermission('compare_collected_invoice_economic_v2');
$collected_invoice_id = $this->requireCollectedInvoiceId();
@@ -303,6 +311,7 @@ class orderInvoicesRoute
/** Collected order invoices > E-conomic V2 compare bulk > POST */
$this->post('/collected-invoices/economic/v2/compare/bulk', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/economic/v2/compare/bulk');
global $response;
$this->requirePermission('compare_collected_invoice_economic_v2_bulk');
self::requireParameters(['collected_invoice_ids']);
@@ -370,6 +379,7 @@ class orderInvoicesRoute
/** Collected order invoices > E-conomic V2 revenue statistics > GET */
$this->get('/collected-invoices/economic/v2/revenue-statistics', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/collected-invoices/economic/v2/revenue-statistics');
global $response;
$this->requirePermission('view_collected_invoice_economic_v2_revenue_statistics');
@@ -413,6 +423,7 @@ class orderInvoicesRoute
/** Collected order invoices > Ready to invoice > GET */
$this->get('/collected-invoices/ready-to-invoice', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/collected-invoices/ready-to-invoice');
global $response;
$this->requirePermission('list_collected_invoices');
$user = (new authentication())->get_user();
@@ -449,6 +460,7 @@ class orderInvoicesRoute
/** Collected order invoices > POST */
$this->post('/collected-invoices', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices');
global $response;
$this->requirePermission('add_collected_invoice');
$user = (new authentication())->get_user();
@@ -523,6 +535,7 @@ class orderInvoicesRoute
/** Collected order invoices > Move to customer > POST */
$this->post('/collected-invoices/move-to-customer', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/move-to-customer');
global $response;
$this->requirePermission('move_collected_invoice_customer');
$user = (new authentication())->get_user();
@@ -566,6 +579,7 @@ class orderInvoicesRoute
/** Collected order invoices > Split > POST */
$this->post('/collected-invoices/split', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/split');
global $response;
$this->requirePermission('split_collected_invoice');
$user = (new authentication())->get_user();
@@ -596,6 +610,7 @@ class orderInvoicesRoute
/** Collected order invoices > Split by month > POST */
$this->post('/collected-invoices/split-by-month', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/split-by-month');
global $response, $db;
$this->requirePermission('split_collected_invoice');
$user = (new authentication())->get_user();
@@ -738,6 +753,7 @@ class orderInvoicesRoute
/** Collected order invoices > Bulk action preview > POST */
$this->post('/collected-invoices/bulk-actions/preview', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/bulk-actions/preview');
global $response;
$user = (new authentication())->get_user();
if (!$user) {
@@ -803,6 +819,7 @@ class orderInvoicesRoute
/** Collected order invoices > Bulk action apply > POST */
$this->post('/collected-invoices/bulk-actions/apply', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/bulk-actions/apply');
global $response;
$user = (new authentication())->get_user();
if (!$user) {
@@ -860,6 +877,7 @@ class orderInvoicesRoute
);
$this->post('/superuser/invoicing/period/tree-actions/preview', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/superuser/invoicing/period/tree-actions/preview');
global $response;
$this->requirePermission('superuser_invoicing_period');
$user = (new authentication())->get_user();
@@ -915,6 +933,7 @@ class orderInvoicesRoute
);
$this->post('/superuser/invoicing/period/tree-actions/apply', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/superuser/invoicing/period/tree-actions/apply');
global $response;
$this->requirePermission('superuser_invoicing_period');
$user = (new authentication())->get_user();
@@ -955,6 +974,7 @@ class orderInvoicesRoute
/** Collected order invoices > E-Conomic > POST (queued) */
$this->post('/collected-invoices/economic', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/economic');
global $response;
$this->requirePermission('add_collected_invoice_economic');
$user = (new authentication())->get_user();
@@ -1049,6 +1069,7 @@ class orderInvoicesRoute
);
$this->get('/collected-invoices/economic/queue', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/collected-invoices/economic/queue');
global $response;
$this->requirePermission('add_collected_invoice_economic');
$user = (new authentication())->get_user();
@@ -1086,6 +1107,7 @@ class orderInvoicesRoute
);
$this->get('/collected-invoices/economic/queue/status', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/collected-invoices/economic/queue/status');
global $response;
$this->requirePermission('add_collected_invoice_economic');
$user = (new authentication())->get_user();
@@ -1105,6 +1127,7 @@ class orderInvoicesRoute
);
$this->get('/collected-invoices/economic/queue/monitor', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/collected-invoices/economic/queue/monitor');
global $response;
$this->requirePermission('add_collected_invoice_economic');
$user = (new authentication())->get_user();
@@ -1128,6 +1151,7 @@ class orderInvoicesRoute
);
$this->post('/collected-invoices/economic/queue/retry', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/economic/queue/retry');
global $response;
$this->requirePermission('add_collected_invoice_economic');
$user = (new authentication())->get_user();
@@ -1162,6 +1186,7 @@ class orderInvoicesRoute
);
$this->post('/collected-invoices/economic/queue/dismiss', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/economic/queue/dismiss');
global $response;
$this->requirePermission('add_collected_invoice_economic');
$user = (new authentication())->get_user();
@@ -1198,6 +1223,7 @@ class orderInvoicesRoute
);
$this->post('/collected-invoices/economic/queue/dismiss-terminal', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/economic/queue/dismiss-terminal');
global $response;
$this->requirePermission('add_collected_invoice_economic');
$user = (new authentication())->get_user();
@@ -1223,6 +1249,7 @@ class orderInvoicesRoute
);
$this->post('/collected-invoices/economic/queue/run', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/economic/queue/run');
global $response;
$this->requirePermission('add_collected_invoice_economic');
$user = (new authentication())->get_user();
@@ -1265,6 +1292,7 @@ class orderInvoicesRoute
/** Collected order invoices > Move multiple > Registration numbers > POST */
$this->post('/collected-invoices/move-multiple/registration-numbers', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/move-multiple/registration-numbers');
global $response;
$this->requirePermission('move_collected_invoice');
$user = (new authentication())->get_user();
@@ -1339,6 +1367,7 @@ class orderInvoicesRoute
});
/** Collected order invoices > Move multiple > POST */
$this->post('/collected-invoices/move-multiple', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/move-multiple');
// Used to move multiple orders, to a new collected order invoice, in one request, instead of having to move each order one by one
global $response;
$this->requirePermission('move_collected_invoice');
@@ -1402,6 +1431,7 @@ class orderInvoicesRoute
/** Collected order invoices > E-Conomic > Unlink and clear cached data > POST */
$this->post('/collected-invoices/economic/unlink', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/economic/unlink');
global $response;
$this->requirePermission('unlink_collected_invoice_economic');
$user = (new authentication())->get_user();
@@ -1433,6 +1463,7 @@ class orderInvoicesRoute
/** Collected order invoices > E-Conomic > Remove special arrangements, and set all items to be included in the invoice > POST */
$this->post('/collected-invoices/remove-special-arrangements', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/remove-special-arrangements');
global $response;
$this->requirePermission('reset_collected_invoice_economic');
$user = (new authentication())->get_user();
@@ -1466,6 +1497,7 @@ class orderInvoicesRoute
);
/** Collected order invoices > E-Conomic > Reset prices of items not included in the invoice > POST */
$this->post('/collected-invoices/reset-prices-of-items-not-included-in-invoice', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/reset-prices-of-items-not-included-in-invoice');
global $response;
$this->requirePermission('reset_collected_invoice_economic');
$user = (new authentication())->get_user();
@@ -1498,6 +1530,7 @@ class orderInvoicesRoute
/** Collected order invoices > Stripe > BOOK > POST */
$this->post('/collected-invoices/stripe/book', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/stripe/book');
global $response;
$this->requirePermission('add_collected_invoice_stripe');
$user = (new authentication())->get_user();
@@ -1580,6 +1613,7 @@ class orderInvoicesRoute
/** Collected order invoices > Vehicle subscriptions > POST */
$this->post('/collected-invoices/vehicle-subscriptions', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/vehicle-subscriptions');
global $response;
$this->requirePermission('add_collected_invoice_vehicle_subscriptions');
$user = (new authentication())->get_user();
@@ -1611,6 +1645,7 @@ class orderInvoicesRoute
/** Collected order invoices > Vehicle subscriptions > POST */
$this->post('/collected-invoices/fixed-price', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/fixed-price');
global $response;
$this->requirePermission('add_collected_invoice_fixed_price');
$user = (new authentication())->get_user();
@@ -1651,6 +1686,7 @@ class orderInvoicesRoute
/** Collected order invoices > Vehicle subscriptions > POST */
$this->post('/collected-invoices/vehicle-subscriptions/custom', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/vehicle-subscriptions/custom');
global $response;
$this->requirePermission('add_collected_invoice_vehicle_subscriptions');
$user = (new authentication())->get_user();
@@ -1717,6 +1753,7 @@ class orderInvoicesRoute
/** Collected order invoices > Open > GET Customers */
$this->get('/collected-invoices/customers', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/collected-invoices/customers');
global $response;
$this->requirePermission('list_collected_invoices');
$user = (new authentication())->get_user();
@@ -1799,6 +1836,7 @@ class orderInvoicesRoute
);
$this->get('/collected-invoices/customers/invoicePerOrder', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/collected-invoices/customers/invoicePerOrder');
global $response;
$this->requirePermission('list_collected_invoices');
$user = (new authentication())->get_user();
@@ -1842,6 +1880,7 @@ class orderInvoicesRoute
);
$this->get('/collected-invoices/customers/invoicePerMonth', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/collected-invoices/customers/invoicePerMonth');
global $response;
$this->requirePermission('list_collected_invoices');
$user = (new authentication())->get_user();
@@ -1886,6 +1925,7 @@ class orderInvoicesRoute
$this->post('/collected-invoices/customers/invoiceTotals', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/customers/invoiceTotals');
// This is a superuser-only route
global $response;
$this->requirePermission('list_collected_invoices');
@@ -1973,6 +2013,7 @@ class orderInvoicesRoute
});
$this->get('/collected-invoices/economic/overview', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/collected-invoices/economic/overview');
global $response;
$this->requirePermission('list_collected_invoices_economic_overview');
$user = (new authentication())->get_user();
@@ -2054,6 +2095,7 @@ class orderInvoicesRoute
);
$this->post('/collected-invoices/economic/run/check-drafts', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/economic/run/check-drafts');
global $response;
$this->requirePermission('module_economic_run_check_drafts');
$user = (new authentication())->get_user();
@@ -2082,6 +2124,7 @@ class orderInvoicesRoute
);
$this->post('/collected-invoices/economic/run/check-errors', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_WRITE, '/collected-invoices/economic/run/check-errors');
global $response;
$this->requirePermission('module_economic_run_check_errors');
$user = (new authentication())->get_user();
@@ -11,6 +11,9 @@ use objects\orders_o;
use objects\products_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class orderItemsRoute
{
use route_t;
@@ -18,6 +21,7 @@ class orderItemsRoute
public function run(): void
{
$this->post('/order/items', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/order/items');
// Require the user to be logged in
global $response;
$this->requirePermission('add_order_items');
@@ -154,6 +158,7 @@ class orderItemsRoute
);
$this->get('/order/items', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/order/items');
// Require the user to be logged in
global $response;
// Check if the user is requesting their own order items
@@ -209,6 +214,7 @@ class orderItemsRoute
);
$this->delete('/order/items', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/order/items');
// Require the user to be logged in
global $response, $db;
$this->requirePermission('delete_order_items');
@@ -262,6 +268,7 @@ class orderItemsRoute
);
$this->put('/order/items', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/order/items');
// Require the user to be logged in
global $response, $db;
$this->requirePermission('edit_order_items');
+6
View File
@@ -8,6 +8,9 @@ use objects\logs_o;
use objects\orders_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class orderRoute
{
use route_t;
@@ -15,6 +18,7 @@ class orderRoute
public function run(): void
{
$this->get('/order', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/order');
// Require the user to be logged in
global /** @var response $response */
$response;
@@ -55,6 +59,7 @@ class orderRoute
);
$this->post('/order/wash-certificate', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/order/wash-certificate');
// Require the user to be logged in and have permission
global /** @var response $response */
$response;
@@ -123,6 +128,7 @@ class orderRoute
/**
* $this->put('/order', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/order');
*
* // Require the user to be logged in
* global $response;
+20
View File
@@ -25,6 +25,9 @@ use objects\stripe_module_orders_o;
use objects\stripe_payment_intents_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
use modules\subusers\helpers\subusers_permission_node_key;
class ordersRoute
@@ -36,6 +39,7 @@ class ordersRoute
public function run(): void
{
$this->get('/orders/reference-suggestions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/orders/reference-suggestions');
global $response;
$auth = new authentication();
$user = $auth->get_user();
@@ -82,6 +86,7 @@ class ordersRoute
);
$this->get('/orders', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/orders');
// Require the user to be logged in
global $response;
/** Authentication */
@@ -150,6 +155,7 @@ class ordersRoute
$this->post('/orders', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/orders');
// Require the user to be logged in
global $response;
$this->requirePermission('add_order');
@@ -253,6 +259,7 @@ class ordersRoute
);
$this->put('/order', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/order');
self::updateOrder();
},
[
@@ -261,6 +268,7 @@ class ordersRoute
);
$this->put('/orders', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/orders');
self::updateOrder();
},
[
@@ -269,6 +277,7 @@ class ordersRoute
);
$this->delete('/orders', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/orders');
// Require the user to be logged in
global $response;
$this->requirePermission('delete_order');
@@ -343,6 +352,7 @@ class ordersRoute
);
$this->get('/orders/attachments/download', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/orders/attachments/download');
global $response;
$context = $this->requireOrderAttachmentDownloadContext();
$downloadLink = $context['store'] instanceof pdf_store
@@ -358,6 +368,7 @@ class ordersRoute
);
$this->get('/orders/attachments/content', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/orders/attachments/content');
global $response;
$context = $this->requireOrderAttachmentDownloadContext();
@@ -401,6 +412,7 @@ class ordersRoute
);
$this->get('/orders/attachments', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/orders/attachments');
// Require the user to be logged in
global $response;
// Get the user object
@@ -456,6 +468,7 @@ class ordersRoute
);
$this->post('/orders/attachments/upload', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/orders/attachments/upload');
// Require the user to be logged in
global $response;
$this->requirePermission('add_order_attachments');
@@ -509,6 +522,7 @@ class ordersRoute
);
$this->delete('/orders/attachments', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/orders/attachments');
// Require the user to be logged in
global $response;
$this->requirePermission('delete_order_attachments');
@@ -556,6 +570,7 @@ class ordersRoute
);
$this->post('/orders/mark_as_completed', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/orders/mark_as_completed');
// Require the user to be logged in
global $response;
$this->requirePermission('mark_order_as_completed');
@@ -596,6 +611,7 @@ class ordersRoute
);
$this->post('/orders/module/stripe/payment_intent', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/orders/module/stripe/payment_intent');
global $response;
$this->requirePermission('charge_order');
$user = (new authentication())->get_user();
@@ -768,6 +784,7 @@ class ordersRoute
);
$this->get('/orders/module/stripe/payment_intent', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/orders/module/stripe/payment_intent');
global $response;
$this->requirePermission('get_payment_intent');
$user = (new authentication())->get_user();
@@ -858,6 +875,7 @@ class ordersRoute
);
$this->delete('/orders/module/stripe/payment_intent', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/orders/module/stripe/payment_intent');
global $response;
$this->requirePermission('charge_order');
$user = (new authentication())->get_user();
@@ -911,6 +929,7 @@ class ordersRoute
);
$this->post('/orders/module/stripe/payment_intent/capture', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/orders/module/stripe/payment_intent/capture');
global $response;
$this->requirePermission('confirm_payment_intent');
$user = (new authentication())->get_user();
@@ -1000,6 +1019,7 @@ class ordersRoute
);
$this->post('/orders/module/stripe/debug/simulate_payment', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/orders/module/stripe/debug/simulate_payment');
// Require the user to be logged in
global $response;
$this->requirePermission('debug_simulate_payment_intent');
@@ -7,6 +7,9 @@ use objects\logs_o;
use objects\passkeys_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class passkeysRoute
{
use route_t;
@@ -46,6 +49,7 @@ class passkeysRoute
{
// List passkeys for current authenticated user
$this->get('/account/security/passkeys', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/account/security/passkeys');
global $response;
$principal = $this->resolvePasskeyPrincipal('user_security_passkeys_list');
@@ -80,6 +84,7 @@ class passkeysRoute
// Create/add a passkey (store after client-side WebAuthn attestation)
$this->post('/account/security/passkeys', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/account/security/passkeys');
global $response;
$principal = $this->resolvePasskeyPrincipal('user_security_passkeys_create');
@@ -132,6 +137,7 @@ class passkeysRoute
// Rename a passkey
$this->patch('/account/security/passkeys/{id}', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/account/security/passkeys/{id}');
global $response;
$principal = $this->resolvePasskeyPrincipal('user_security_passkeys_rename');
@@ -162,6 +168,7 @@ class passkeysRoute
// Delete a passkey (soft delete)
$this->delete('/account/security/passkeys/{id}', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/account/security/passkeys/{id}');
global $response;
$principal = $this->resolvePasskeyPrincipal('user_security_passkeys_delete');
@@ -8,6 +8,9 @@ use classes\response;
use classes\router;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class pdfGeneratorRoute
{
use route_t;
@@ -20,6 +23,7 @@ class pdfGeneratorRoute
/** PDF Generator > GET */
$this->get('/modules/pdf-generator/test', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/pdf-generator/test');
global $response;
// Check if the required parameters are present
self::requireParameters([
@@ -123,6 +127,7 @@ class pdfGeneratorRoute
);
$this->get('/modules/pdf-generator/material/order', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/modules/pdf-generator/material/order');
self::requireParameters([
'id'
]);
@@ -8,6 +8,9 @@ use objects\logs_o;
use objects\plate_scanners_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class plateScannersRoute
{
use route_t;
@@ -15,6 +18,7 @@ class plateScannersRoute
public function run(): void
{
$this->get('/numberplatescanners', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/numberplatescanners');
// Require the user to be logged in
global $response;
$this->requirePermission('list_number_plate_scanners');
@@ -53,6 +57,7 @@ class plateScannersRoute
);
$this->post('/numberplatescanners', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/numberplatescanners');
// Require the user to be logged in
global $response;
$this->requirePermission('add_number_plate_scanner');
@@ -98,6 +103,7 @@ class plateScannersRoute
);
$this->put('/numberplatescanners', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/numberplatescanners');
// Require the user to be logged in
global $response;
$this->requirePermission('edit_number_plate_scanner');
@@ -152,6 +158,7 @@ class plateScannersRoute
);
$this->post('/numberplatescanners/{id}/rotate-key', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/numberplatescanners/{id}/rotate-key');
global $response;
$this->requirePermission('edit_number_plate_scanner');
$user = (new authentication())->get_user();
@@ -10,6 +10,9 @@ use objects\plate_scans_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class plateScansRoute
{
use route_t;
@@ -18,6 +21,7 @@ class plateScansRoute
{
$this->post('/numberplatescans', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/numberplatescans');
// Require the user to be logged in
global $response;
$this->requirePlateScannerAuth();
@@ -52,6 +56,7 @@ class plateScansRoute
});
$this->post('/numberplatescans/department', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/numberplatescans/department');
// Require the user to be logged in
global $response;
$this->requirePermission('list_number_plate_scans_department');
@@ -89,6 +94,7 @@ class plateScansRoute
]);
$this->get('/numberplatescans', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/numberplatescans');
// Require the user to be logged in
global $response;
$this->requirePermission('list_number_plate_scans');
@@ -7,6 +7,9 @@ use objects\logs_o;
use objects\xlvask_potential_order_matches_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class potentialOrderMatchesRoute
{
use route_t;
@@ -14,6 +17,7 @@ class potentialOrderMatchesRoute
public function run(): void
{
$this->get('/orders/sync/potential-matches', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/orders/sync/potential-matches');
// Require the user to be logged in
global $response;
$this->requirePermission('list_potential_order_matches');
@@ -83,6 +87,7 @@ class potentialOrderMatchesRoute
);
$this->post('/orders/sync/potential-matches/ignore-duplicate', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/orders/sync/potential-matches/ignore-duplicate');
// Require the user to be logged in
global $response;
$this->requirePermission('ignore_duplicate_potential_order_matches');
@@ -7,6 +7,9 @@ use objects\logs_o;
use objects\product_options_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class productOptionsRoute
{
use route_t;
@@ -14,6 +17,7 @@ class productOptionsRoute
public function run(): void
{
$this->get('/product/options', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/product/options');
// Require the user to be logged in
global $response;
@@ -67,6 +71,7 @@ class productOptionsRoute
);
$this->post('/product/options', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/product/options');
// Require the user to be logged in
global $response;
$this->requirePermission('add_product_option');
@@ -105,6 +110,7 @@ class productOptionsRoute
);
$this->put('/product/options', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/product/options');
// Require the user to be logged in
global $response;
$this->requirePermission('edit_product_option');
@@ -163,6 +169,7 @@ class productOptionsRoute
);
$this->delete('/product/options', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/product/options');
// Require the user to be logged in
global $response;
$this->requirePermission('delete_product_option');
@@ -12,6 +12,9 @@ use objects\products_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class productsRoute
{
use route_t;
@@ -218,6 +221,7 @@ class productsRoute
public function run(): void
{
$this->get('/products', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/products');
// Check if the user is logged in
global $response;
$permission_node = 'list_products';
@@ -447,6 +451,7 @@ class productsRoute
);
$this->post('/products', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/products');
// Require the user to be logged in
global $response;
$this->requirePermission('add_product');
@@ -494,6 +499,7 @@ class productsRoute
);
$this->put('/products', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/products');
// Require the user to be logged in
global $response;
$this->requirePermission('edit_product');
@@ -567,6 +573,7 @@ class productsRoute
// but is marked as merged in the products table. Reads and new orders should follow
// merged_into_product_id to the target. An audit row is written to product_merges.
$this->post('/products/{id}/merge', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/products/{id}/merge');
global $response;
$this->requirePermission('edit_product');
$user = (new authentication())->get_user();
@@ -7,6 +7,9 @@ use classes\release_manager;
use Throwable;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class releaseManagerRoute
{
use route_t;
@@ -14,16 +17,19 @@ class releaseManagerRoute
public function run(): void
{
$this->get('/release/bootstrap', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/release/bootstrap');
global $response;
$response->success((new release_manager())->bootstrap());
});
$this->get('/release/runtime', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/release/runtime');
global $response;
$response->success((new release_manager())->runtimeForCurrentPrincipal($this->getParametersAsArray()));
});
$this->post('/release/timeline/events', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/release/timeline/events');
global $response;
$payload = $this->requestPayload();
$events = is_array($payload['events'] ?? null) ? $payload['events'] : ($payload['event'] ?? $payload);
@@ -35,6 +41,7 @@ class releaseManagerRoute
});
$this->post('/release/github/webhook', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/release/github/webhook');
global $response;
try {
$headers = function_exists('getallheaders') ? getallheaders() : [];
@@ -46,6 +53,7 @@ class releaseManagerRoute
});
$this->post('/release/gate/test-runs', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/release/gate/test-runs');
global $response;
$manager = new release_manager();
if (!$manager->verifyReleaseGateToken($this->releaseGateToken())) {
@@ -60,6 +68,7 @@ class releaseManagerRoute
});
$this->post('/release/gate/frontend-version', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/release/gate/frontend-version');
global $response;
$manager = new release_manager();
if (!$manager->verifyReleaseGateToken($this->releaseGateToken())) {
@@ -86,6 +95,7 @@ class releaseManagerRoute
});
$this->get('/release/gate/frontend-version', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/release/gate/frontend-version');
global $response;
$manager = new release_manager();
if (!$manager->verifyReleaseGateToken($this->releaseGateToken())) {
@@ -98,6 +108,7 @@ class releaseManagerRoute
});
$this->get('/superuser/releases', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases');
global $response;
$this->requirePermission('superuser_release_manager_view');
$response->success((new release_manager())->summary());
@@ -106,6 +117,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/config');
global $response;
$this->requirePermission('superuser_release_manager_view');
$response->success((new release_manager())->releaseConfig());
@@ -114,6 +126,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/operations', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/operations');
global $response;
$this->requirePermission('superuser_release_manager_view');
$response->success((new release_manager())->listOperations($this->getParametersAsArray()));
@@ -122,6 +135,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/operations/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/operations/{id}');
global $response;
$this->requirePermission('superuser_release_manager_view');
try {
@@ -134,6 +148,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/test-runs', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/test-runs');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
$response->success((new release_manager())->runReleaseTest($this->requestPayload(), $this->actorUserId()), 202);
@@ -142,6 +157,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/coolify-cleanup/preview', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/coolify-cleanup/preview');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
try {
@@ -154,6 +170,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/coolify-cleanup/apply', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/coolify-cleanup/apply');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
$this->requirePermission('superuser_coolify_manage');
@@ -168,6 +185,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/config', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/config');
global $response;
$this->requirePermission('superuser_release_manager_manage');
try {
@@ -180,6 +198,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/github/repositories', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/github/repositories');
global $response;
$this->requirePermission('superuser_release_manager_view');
try {
@@ -192,6 +211,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/github/branches', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/github/branches');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
try {
@@ -204,6 +224,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/github/commits', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/github/commits');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
try {
@@ -216,6 +237,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/github/test', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/github/test');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
$response->success((new release_manager())->testGithubRepositoryAccess($this->requestPayload()));
@@ -224,6 +246,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/channels', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/channels');
global $response;
$this->requirePermission('superuser_release_manager_view');
$response->success((new release_manager())->listChannels());
@@ -232,6 +255,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/channels', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/channels');
global $response;
$this->requirePermission('superuser_release_manager_manage');
try {
@@ -244,6 +268,7 @@ class releaseManagerRoute
]);
$this->patch('/superuser/releases/channels/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/channels/{id}');
global $response;
$this->requirePermission('superuser_release_manager_manage');
try {
@@ -256,6 +281,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/channels/{id}/rollback', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/channels/{id}/rollback');
global $response;
$this->requirePermission('superuser_release_manager_rollback');
try {
@@ -268,6 +294,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/channels/{id}/sync', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/channels/{id}/sync');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
try {
@@ -280,6 +307,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/channels/{id}/bundle', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/channels/{id}/bundle');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
try {
@@ -292,6 +320,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/assignments', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/assignments');
global $response;
$this->requirePermission('superuser_release_manager_view');
$response->success((new release_manager())->listAssignments());
@@ -300,6 +329,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/assignment-subjects', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/assignment-subjects');
global $response;
$this->requirePermission('superuser_release_manager_manage');
$response->success((new release_manager())->searchAssignmentSubjects($this->getParametersAsArray()));
@@ -308,6 +338,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/assignments', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/assignments');
global $response;
$this->requirePermission('superuser_release_manager_manage');
try {
@@ -320,6 +351,7 @@ class releaseManagerRoute
]);
$this->delete('/superuser/releases/assignments/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/assignments/{id}');
global $response;
$this->requirePermission('superuser_release_manager_manage');
try {
@@ -332,6 +364,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/targets', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/targets');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
$response->success((new release_manager())->listDeploymentTargets());
@@ -340,6 +373,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/targets', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/targets');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
try {
@@ -352,6 +386,7 @@ class releaseManagerRoute
]);
$this->delete('/superuser/releases/targets/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/targets/{id}');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
try {
@@ -364,6 +399,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/service-sets', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/service-sets');
global $response;
$this->requirePermission('superuser_release_manager_view');
$response->success((new release_manager())->listServiceSets());
@@ -372,6 +408,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/service-sets', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/service-sets');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
try {
@@ -384,6 +421,7 @@ class releaseManagerRoute
]);
$this->delete('/superuser/releases/service-sets/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/service-sets/{id}');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
try {
@@ -402,6 +440,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/service-sets/{id}/isolated-data-services', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/service-sets/{id}/isolated-data-services');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
try {
@@ -421,6 +460,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/bundles', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/bundles');
global $response;
$this->requirePermission('superuser_release_manager_view');
$limit = (int)($this->getParameter('limit') ?? 50);
@@ -430,6 +470,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/bundles', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/bundles');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
try {
@@ -442,6 +483,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/bundles/{id}/deploy', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/bundles/{id}/deploy');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
try {
@@ -454,6 +496,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/bundles/{id}/promote', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/bundles/{id}/promote');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
try {
@@ -466,6 +509,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/deployments', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/deployments');
global $response;
$this->requirePermission('superuser_release_manager_view');
$limit = (int)($this->getParameter('limit') ?? 50);
@@ -475,6 +519,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/deployments', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/deployments');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
try {
@@ -487,6 +532,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/deployments/{id}/promote', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/deployments/{id}/promote');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
try {
@@ -499,6 +545,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/issues/actions', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/issues/actions');
global $response;
$this->requirePermission('superuser_release_manager_deploy');
$response->success((new release_manager())->runIssueAction($this->requestPayload(), $this->actorUserId()));
@@ -507,6 +554,7 @@ class releaseManagerRoute
]);
$this->post('/superuser/releases/replay-targets', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/releases/replay-targets');
global $response;
$this->requirePermission('superuser_release_manager_replay');
try {
@@ -519,6 +567,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/timeline/sessions', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/timeline/sessions');
global $response;
$this->requirePermission('superuser_release_manager_replay');
$response->success((new release_manager())->listTimelineSessions($this->getParametersAsArray()));
@@ -527,6 +576,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/timeline/sessions/{traceId}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/timeline/sessions/{traceId}');
global $response;
$this->requirePermission('superuser_release_manager_replay');
try {
@@ -539,6 +589,7 @@ class releaseManagerRoute
]);
$this->get('/superuser/releases/timeline', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/releases/timeline');
global $response;
$this->requirePermission('superuser_release_manager_replay');
$response->success((new release_manager())->searchTimeline($this->getParametersAsArray()));
@@ -6,6 +6,9 @@ use classes\authentication;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class sessionRoute
{
use route_t;
@@ -13,6 +16,7 @@ class sessionRoute
public function run(): void
{
$this->get('/auth/session', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/auth/session');
// Require the user to be logged in
global $response;
$this->requirePermission('fetch_session');
@@ -7,6 +7,8 @@ use classes\response;
use classes\statistics;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class statisticsRoute
{
@@ -16,6 +18,7 @@ class statisticsRoute
{
/** Statistics >> Bookings >> New bookings */
$this->get('/statistics/bookings/new', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/statistics/bookings/new');
// Require the user to be logged in
global
/** @var response $response */
@@ -28,6 +28,9 @@ use modules\subusers\permissions\subusers_permission_nodes_vehicles;
use modules\subusers\helpers\subusers_permission_node_key;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class subusersRoute
{
use route_t;
@@ -1906,6 +1909,7 @@ class subusersRoute
// Subuser Grant Management
// =============================
$this->get('/subusers/grants', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_READ, '/subusers/grants');
global $response;
/** Permissions (subuser-aware) */
$permission_own = self::definePermission('list_own_subuser_grants', subusers_permission_node_key::SUBUSERS_LIST);
@@ -1988,6 +1992,7 @@ class subusersRoute
]);
$this->post('/subusers/grants', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/subusers/grants');
global $response;
/** Permissions (subuser-aware) */
$permission_own = self::definePermission('add_own_subusers', subusers_permission_node_key::SUBUSERS_ADD);
@@ -2045,6 +2050,7 @@ class subusersRoute
]);
$this->put('/subusers/grants', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/subusers/grants');
global $response;
/** Permissions (subuser-aware) */
$permission_own = self::definePermission('edit_own_subusers', subusers_permission_node_key::SUBUSERS_EDIT);
@@ -2120,6 +2126,7 @@ class subusersRoute
);
$this->get('/subusers/permission-nodes', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_READ, '/subusers/permission-nodes');
global $response;
$canUseGlobalManagement = $this->hasPermission('manage_subuser_grants')
|| $this->hasPermission('list_subusers')
@@ -2165,6 +2172,7 @@ class subusersRoute
]);
$this->get('/subusers/permission-templates', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_READ, '/subusers/permission-templates');
global $response;
$canUseGlobalManagement = $this->hasPermission('manage_subuser_grants')
|| $this->hasPermission('list_subusers')
@@ -2183,10 +2191,13 @@ class subusersRoute
'edit_subusers' => 'List chauffeur permission templates while editing chauffeur grants.',
]);
// Public registration endpoint — must stay publicly accessible (no
// scope check); new drivers cannot hold a scope before they exist.
$this->post('/subusers', function () {
$this->registerPublicSubuser();
});
$this->get('/subusers/setup', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_READ, '/subusers/setup');
// Require the user to be logged in
global $response;
self::requireParameters(['token']);
@@ -2201,6 +2212,7 @@ class subusersRoute
$response->success(['message' => 'Token is valid', 'subuser_id' => $subuser->id]);
});
$this->post('/subusers/setup', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/subusers/setup');
// Require the user to be logged in
global $response;
self::requireParameters(['token', 'password', 'name']);
@@ -2297,6 +2309,7 @@ class subusersRoute
});
$this->post('/subusers/password-reset/request', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/subusers/password-reset/request');
global $response;
$this->requireRecaptcha();
@@ -2351,6 +2364,7 @@ class subusersRoute
});
$this->get('/subusers/password-reset/validate', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_READ, '/subusers/password-reset/validate');
global $response;
self::requireParameters(['token']);
$record = (new subuser_action_token_service())->inspect(
@@ -2364,6 +2378,7 @@ class subusersRoute
});
$this->post('/subusers/password-reset/set', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/subusers/password-reset/set');
global $response;
$this->requireRecaptcha();
self::requireParameters(['token', 'password']);
@@ -2389,6 +2404,7 @@ class subusersRoute
});
$this->get('/subusers/access-decision', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_READ, '/subusers/access-decision');
global $response;
self::requireParameters(['token']);
$record = (new subuser_action_token_service())->inspect((string)self::getParameter('token'));
@@ -2425,6 +2441,7 @@ class subusersRoute
});
$this->post('/subusers/access-decision', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/subusers/access-decision');
global $response;
self::requireParameters(['token']);
$token = (string)self::getParameter('token');
@@ -2461,6 +2478,7 @@ class subusersRoute
});
$this->post('/subusers/auth/password', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/subusers/auth/password');
global $response;
/**
* Username types:
@@ -2539,6 +2557,7 @@ class subusersRoute
});
$this->post('/subusers/me/password', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/subusers/me/password');
global $response;
$subuser = (new authentication())->get_subuser();
if ($subuser === false) {
@@ -2568,6 +2587,7 @@ class subusersRoute
// Subusers - List & Get (with grant visibility)
// =============================
$this->get('/superuser/subusers', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_READ, '/superuser/subusers');
global $response;
$this->requirePermission('list_subusers');
$response->success($this->listSuperuserSubusers());
@@ -2576,6 +2596,7 @@ class subusersRoute
]);
$this->patch('/superuser/subusers/{subuser_id}', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/superuser/subusers/{subuser_id}');
global $response;
$this->requirePermission('edit_subusers');
@@ -2605,6 +2626,7 @@ class subusersRoute
]);
$this->post('/superuser/subusers/{subuser_id}/verification/{channel}/send', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/superuser/subusers/{subuser_id}/verification/{channel}/send');
global $response;
$this->requirePermission('edit_subusers');
@@ -2625,6 +2647,7 @@ class subusersRoute
]);
$this->patch('/superuser/subusers/{subuser_id}/verification/{channel}', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/superuser/subusers/{subuser_id}/verification/{channel}');
global $response;
$this->requirePermission('edit_subusers');
@@ -2658,6 +2681,7 @@ class subusersRoute
]);
$this->post('/superuser/subusers/{subuser_id}/password', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/superuser/subusers/{subuser_id}/password');
global $response;
$this->requirePermission('edit_subusers');
@@ -2691,6 +2715,7 @@ class subusersRoute
]);
$this->post('/superuser/subusers/{subuser_id}/login-link', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/superuser/subusers/{subuser_id}/login-link');
global $response;
$this->requirePermission('edit_subusers');
@@ -2708,6 +2733,7 @@ class subusersRoute
]);
$this->post('/superuser/subusers/{subuser_id}/password-guide/{channel}/send', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/superuser/subusers/{subuser_id}/password-guide/{channel}/send');
$this->sendSuperuserSubuserDirectLoginLink('password_guide');
}, [
'edit_subusers' => 'Send chauffeur password guide links as a superuser.',
@@ -2715,6 +2741,7 @@ class subusersRoute
]);
$this->post('/superuser/subusers/{subuser_id}/login-link/{channel}/send', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/superuser/subusers/{subuser_id}/login-link/{channel}/send');
$this->sendSuperuserSubuserDirectLoginLink('login_link');
}, [
'edit_subusers' => 'Send chauffeur direct login links as a superuser.',
@@ -2722,6 +2749,7 @@ class subusersRoute
]);
$this->get('/superuser/users/{user_id}/subusers', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_READ, '/superuser/users/{user_id}/subusers');
global $response;
$this->requirePermission('list_subusers');
$targetUser = $this->resolveSuperuserSubuserTargetUser($this->routePositiveInt('user_id'));
@@ -2732,6 +2760,7 @@ class subusersRoute
]);
$this->get('/superuser/users/{user_id}/subusers/summary', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_READ, '/superuser/users/{user_id}/subusers/summary');
global $response;
$this->requirePermission('list_subusers');
$targetUser = $this->resolveSuperuserSubuserTargetUser($this->routePositiveInt('user_id'));
@@ -2742,6 +2771,7 @@ class subusersRoute
]);
$this->get('/subusers', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_READ, '/subusers');
global $response;
$customerNumber = $this->requireManagedCustomerScope(subusers_permission_node_key::SUBUSERS_LIST);
$customerName = $this->resolveCustomerName($customerNumber);
@@ -2777,6 +2807,7 @@ class subusersRoute
]);
$this->get('/subusers/me', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_READ, '/subusers/me');
global $response;
$subuser = (new authentication())->get_subuser();
if ($subuser === false) {
@@ -2787,6 +2818,7 @@ class subusersRoute
}, []);
$this->get('/subusers/me/verification', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_READ, '/subusers/me/verification');
global $response;
$subuser = (new authentication())->get_subuser();
if ($subuser === false) {
@@ -2797,6 +2829,7 @@ class subusersRoute
}, []);
$this->post('/subusers/me/verification/{channel}/send', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/subusers/me/verification/{channel}/send');
global $response;
$subuser = (new authentication())->get_subuser();
if ($subuser === false) {
@@ -2816,6 +2849,7 @@ class subusersRoute
}, []);
$this->post('/subusers/me/verification/{channel}/verify', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/subusers/me/verification/{channel}/verify');
global $response;
$subuser = (new authentication())->get_subuser();
if ($subuser === false) {
@@ -2838,6 +2872,7 @@ class subusersRoute
}, []);
$this->post('/subusers/{subuser_id}/verification/{channel}/send', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/subusers/{subuser_id}/verification/{channel}/send');
global $response;
$subuser = $this->loadSubuserOrFail($this->routePositiveInt('subuser_id'));
@@ -2863,6 +2898,7 @@ class subusersRoute
]);
$this->put('/subusers/me', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/subusers/me');
global $response;
$subuser = (new authentication())->get_subuser();
if ($subuser === false) {
@@ -2922,6 +2958,7 @@ class subusersRoute
}, []);
$this->post('/superuser/subusers/invite', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/superuser/subusers/invite');
self::requireParameters(['customer_number']);
$this->requirePermission('add_subusers');
$customerNumber = (int)self::getParameter('customer_number');
@@ -2932,6 +2969,7 @@ class subusersRoute
]);
$this->post('/superuser/users/{user_id}/subusers/invite', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/superuser/users/{user_id}/subusers/invite');
$this->requirePermission('add_subusers');
$targetUser = $this->resolveSuperuserSubuserTargetUser($this->routePositiveInt('user_id'));
$this->handleInviteSubuserForCustomer((int)$targetUser['customer_number']);
@@ -2940,6 +2978,7 @@ class subusersRoute
]);
$this->post('/subusers/invite', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/subusers/invite');
$customerNumber = $this->requireManagedCustomerScope(subusers_permission_node_key::SUBUSERS_ADD);
$this->handleInviteSubuserForCustomer($customerNumber);
}, [
@@ -2947,6 +2986,7 @@ class subusersRoute
]);
$this->post('/superuser/subusers/invite/resend', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/superuser/subusers/invite/resend');
global $response;
$this->requirePermission('edit_subusers');
@@ -2982,6 +3022,7 @@ class subusersRoute
]);
$this->post('/superuser/users/{user_id}/subusers/{subuser_id}/invite/resend', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/superuser/users/{user_id}/subusers/{subuser_id}/invite/resend');
$this->requirePermission('edit_subusers');
$targetUser = $this->resolveSuperuserSubuserTargetUser($this->routePositiveInt('user_id'));
$this->resendInviteForScopedUser(
@@ -2993,6 +3034,7 @@ class subusersRoute
]);
$this->patch('/superuser/users/{user_id}/subusers/grants/{grant_id}', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/superuser/users/{user_id}/subusers/grants/{grant_id}');
$this->requirePermission('manage_subuser_grants');
$targetUser = $this->resolveSuperuserSubuserTargetUser($this->routePositiveInt('user_id'));
$this->patchScopedSubuserGrant(
@@ -3004,6 +3046,7 @@ class subusersRoute
]);
$this->post('/subusers/invite/resend', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/subusers/invite/resend');
global $response;
self::requireParameters(['id']);
@@ -3037,6 +3080,7 @@ class subusersRoute
]);
$this->put('/subusers', function () {
ScopeMiddleware::requireScope(Scope::SUBUSER_WRITE, '/subusers');
global $response;
$this->requireManagedCustomerScope(subusers_permission_node_key::SUBUSERS_EDIT);
$response->error('Customers can only manage subuser grants. Drivers own their account profile.', 403);
@@ -3044,6 +3088,8 @@ class subusersRoute
'edit_own_subusers' => 'Customers cannot edit chauffeur account profiles. They may only manage grants, permissions, and enabled state.',
]);
// Public registration endpoint (alias of POST /subusers) matching OpenAPI: POST /subusers/me
// Must stay publicly accessible — no scope check here; new drivers do
// not hold a scope before they exist.
$this->post('/subusers/me', function () {
$this->registerPublicSubuser();
});
@@ -7,6 +7,9 @@ use classes\coolify_manager;
use Throwable;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class superuserCoolifyRoute
{
use route_t;
@@ -14,6 +17,7 @@ class superuserCoolifyRoute
public function run(): void
{
$this->get('/superuser/coolify', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/coolify');
global $response;
$this->requirePermission('superuser_coolify_view');
@@ -23,6 +27,7 @@ class superuserCoolifyRoute
]);
$this->get('/superuser/coolify/load-balancer', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/coolify/load-balancer');
global $response;
$this->requirePermission('superuser_coolify_view');
@@ -32,6 +37,7 @@ class superuserCoolifyRoute
]);
$this->post('/superuser/coolify/load-balancer/reconcile', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/coolify/load-balancer/reconcile');
global $response;
$this->requirePermission('superuser_coolify_manage');
@@ -53,6 +59,7 @@ class superuserCoolifyRoute
]);
$this->post('/superuser/coolify/load-balancer/routes/deploy', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/coolify/load-balancer/routes/deploy');
global $response;
$this->requirePermission('superuser_coolify_manage');
@@ -74,6 +81,7 @@ class superuserCoolifyRoute
]);
$this->post('/superuser/coolify/load-balancer/api/deploy', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/coolify/load-balancer/api/deploy');
global $response;
$this->requirePermission('superuser_coolify_manage');
@@ -98,6 +106,7 @@ class superuserCoolifyRoute
]);
$this->get('/superuser/coolify/gateways', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/coolify/gateways');
global $response;
$this->requirePermission('superuser_coolify_view');
@@ -107,6 +116,7 @@ class superuserCoolifyRoute
]);
$this->post('/superuser/coolify/gateways', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/coolify/gateways');
global $response;
$this->requirePermission('superuser_coolify_manage');
@@ -123,6 +133,7 @@ class superuserCoolifyRoute
]);
$this->post('/superuser/coolify/gateways/{id}/test', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/coolify/gateways/{id}/test');
global $response;
$this->requirePermission('superuser_coolify_manage');
@@ -139,6 +150,7 @@ class superuserCoolifyRoute
]);
$this->post('/superuser/coolify/instances', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/coolify/instances');
global $response;
$this->requirePermission('superuser_coolify_manage');
@@ -155,6 +167,7 @@ class superuserCoolifyRoute
]);
$this->post('/superuser/coolify/instances/{id}/test', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/coolify/instances/{id}/test');
global $response;
$this->requirePermission('superuser_coolify_manage');
@@ -164,6 +177,7 @@ class superuserCoolifyRoute
]);
$this->get('/superuser/coolify/instances/{id}/placement', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/coolify/instances/{id}/placement');
global $response;
$this->requirePermission('superuser_coolify_view');
@@ -177,6 +191,7 @@ class superuserCoolifyRoute
]);
$this->get('/superuser/coolify/targets', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/coolify/targets');
global $response;
$this->requirePermission('superuser_coolify_view');
@@ -187,6 +202,7 @@ class superuserCoolifyRoute
]);
$this->post('/superuser/coolify/targets', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/coolify/targets');
global $response;
$this->requirePermission('superuser_coolify_manage');
@@ -203,6 +219,7 @@ class superuserCoolifyRoute
]);
$this->post('/superuser/coolify/targets/{id}/reconcile', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/coolify/targets/{id}/reconcile');
global $response;
$this->requirePermission('superuser_coolify_reconcile');
@@ -220,6 +237,7 @@ class superuserCoolifyRoute
]);
$this->post('/superuser/coolify/targets/{id}/deploy', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/coolify/targets/{id}/deploy');
global $response;
$this->requirePermission('superuser_coolify_reconcile');
@@ -237,6 +255,7 @@ class superuserCoolifyRoute
]);
$this->post('/superuser/coolify/targets/{id}/restart', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/coolify/targets/{id}/restart');
global $response;
$this->requirePermission('superuser_coolify_reconcile');
@@ -254,6 +273,7 @@ class superuserCoolifyRoute
]);
$this->post('/superuser/coolify/targets/{id}/failover', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/coolify/targets/{id}/failover');
global $response;
$this->requirePermission('superuser_coolify_failover');
@@ -267,6 +287,7 @@ class superuserCoolifyRoute
]);
$this->delete('/superuser/coolify/targets/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/coolify/targets/{id}');
global $response;
$this->requirePermission('superuser_coolify_manage');
@@ -8,6 +8,9 @@ use classes\customer_rule_product_restriction_service;
use Throwable;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class superuserCustomerRuleProductRestrictionsRoute
{
use route_t;
@@ -15,6 +18,7 @@ class superuserCustomerRuleProductRestrictionsRoute
public function run(): void
{
$this->get('/superuser/customer-rules/product-restrictions', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/customer-rules/product-restrictions');
global $response;
$this->requireClassicSuperuserAnyPermission([
'superuser_customer_rules_view',
@@ -26,6 +30,7 @@ class superuserCustomerRuleProductRestrictionsRoute
]);
$this->put('/superuser/customer-rules/product-restrictions/{attribute}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/customer-rules/product-restrictions/{attribute}');
global $response;
$this->requireClassicSuperuserPermission('superuser_customer_rules_manage');
$attribute = trim((string)$this->fromRoute('attribute'));
@@ -13,6 +13,9 @@ use objects\products_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class superuserDepartmentRoute
{
use route_t;
@@ -20,6 +23,7 @@ class superuserDepartmentRoute
public function run(): void
{
$this->get('/superuser/department', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/department');
// Require the user to be logged in
global $response;
$this->requirePermission('superuser_fetch_department');
@@ -55,6 +59,7 @@ class superuserDepartmentRoute
]);
$this->put('/superuser/department/branding', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/department/branding');
global $response;
$this->requirePermission('superuser_set_department_branding');
@@ -112,6 +117,7 @@ class superuserDepartmentRoute
]);
$this->post('/superuser/department/prices', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/department/prices');
// Require the user to be logged in
global $response;
$this->requirePermission('superuser_set_department_prices');
@@ -174,6 +180,7 @@ class superuserDepartmentRoute
]);
$this->get('/superuser/department/prices', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/department/prices');
// Require the user to be logged in
global $response;
$this->requirePermission('superuser_fetch_department_prices');
@@ -217,6 +224,7 @@ class superuserDepartmentRoute
]);
$this->get('/superuser/department/customer-pricing', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/department/customer-pricing');
global $response;
$this->requirePermission('superuser_fetch_department_customer_pricing');
@@ -240,6 +248,7 @@ class superuserDepartmentRoute
]);
$this->put('/superuser/department/customer-pricing', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/department/customer-pricing');
global $response;
$this->requirePermission('superuser_set_department_customer_pricing');
@@ -268,6 +277,7 @@ class superuserDepartmentRoute
]);
$this->get('/superuser/department/variables', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/department/variables');
// Require the user to be logged in
global $response;
$this->requirePermission('superuser_fetch_department_variables');
@@ -296,6 +306,7 @@ class superuserDepartmentRoute
]);
$this->post('/superuser/department/variables', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/department/variables');
// Require the user to be logged in
global $response;
$this->requirePermission('superuser_set_department_variables');
@@ -6,6 +6,9 @@ use classes\authentication;
use classes\replication_manager;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class superuserReplicationRoute
{
use route_t;
@@ -15,6 +18,7 @@ class superuserReplicationRoute
public function run(): void
{
$this->get('/superuser/replication', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/replication');
global $response;
$this->requireClassicSuperuserPermission('superuser_replication_view');
@@ -25,6 +29,7 @@ class superuserReplicationRoute
]);
$this->post('/superuser/replication/databases', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/replication/databases');
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
@@ -32,6 +37,7 @@ class superuserReplicationRoute
]);
$this->post('/superuser/replication/redis', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/replication/redis');
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
@@ -39,6 +45,7 @@ class superuserReplicationRoute
]);
$this->post('/superuser/replication/minio', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/replication/minio');
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
@@ -46,6 +53,7 @@ class superuserReplicationRoute
]);
$this->post('/superuser/replication/compose-template', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/replication/compose-template');
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
@@ -53,6 +61,7 @@ class superuserReplicationRoute
]);
$this->post('/superuser/replication/test-credentials', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/replication/test-credentials');
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
@@ -60,6 +69,7 @@ class superuserReplicationRoute
]);
$this->post('/superuser/replication/{kind}/{id}/test', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/replication/{kind}/{id}/test');
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
@@ -67,6 +77,7 @@ class superuserReplicationRoute
]);
$this->post('/superuser/replication/{kind}/{id}/provision', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/replication/{kind}/{id}/provision');
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
@@ -74,6 +85,7 @@ class superuserReplicationRoute
]);
$this->post('/superuser/replication/{kind}/{id}/promote', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/replication/{kind}/{id}/promote');
$this->requireClassicSuperuserPermission('superuser_replication_promote');
$this->rejectRetiredManagement();
}, [
@@ -81,6 +93,7 @@ class superuserReplicationRoute
]);
$this->patch('/superuser/replication/{kind}/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/replication/{kind}/{id}');
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
@@ -88,6 +101,7 @@ class superuserReplicationRoute
]);
$this->delete('/superuser/replication/{kind}/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/replication/{kind}/{id}');
$this->requireClassicSuperuserPermission('superuser_replication_remove');
$this->rejectRetiredManagement();
}, [
@@ -7,6 +7,9 @@ use classes\security_policy_service;
use Throwable;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
require_once WD . '/classes/security_policy_service.php';
class superuserSecurityRoute
@@ -16,6 +19,7 @@ class superuserSecurityRoute
public function run(): void
{
$this->get('/superuser/system/security/summary', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/system/security/summary');
global $response;
$this->requireClassicSuperuserPermission('superuser_security_view');
@@ -25,6 +29,7 @@ class superuserSecurityRoute
]);
$this->get('/superuser/system/security/settings', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/system/security/settings');
global $response;
$this->requireClassicSuperuserPermission('superuser_security_view');
@@ -35,6 +40,7 @@ class superuserSecurityRoute
]);
$this->patch('/superuser/system/security/settings', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/system/security/settings');
global $response;
$this->requireClassicSuperuserPermission('superuser_security_settings_manage');
@@ -51,6 +57,7 @@ class superuserSecurityRoute
]);
$this->get('/superuser/system/security/firewall-rules', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/system/security/firewall-rules');
global $response;
$this->requireClassicSuperuserPermission('superuser_security_view');
@@ -60,6 +67,7 @@ class superuserSecurityRoute
]);
$this->post('/superuser/system/security/firewall-rules', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/system/security/firewall-rules');
global $response;
$this->requireClassicSuperuserPermission('superuser_security_firewall_manage');
@@ -76,6 +84,7 @@ class superuserSecurityRoute
]);
$this->patch('/superuser/system/security/firewall-rules/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/system/security/firewall-rules/{id}');
global $response;
$this->requireClassicSuperuserPermission('superuser_security_firewall_manage');
@@ -93,6 +102,7 @@ class superuserSecurityRoute
]);
$this->delete('/superuser/system/security/firewall-rules/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/system/security/firewall-rules/{id}');
global $response;
$this->requireClassicSuperuserPermission('superuser_security_firewall_manage');
@@ -109,6 +119,7 @@ class superuserSecurityRoute
]);
$this->get('/superuser/system/security/incidents', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/system/security/incidents');
global $response;
$this->requireClassicSuperuserPermission('superuser_security_view');
@@ -118,6 +129,7 @@ class superuserSecurityRoute
]);
$this->get('/superuser/system/security/incidents/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/system/security/incidents/{id}');
global $response;
$this->requireClassicSuperuserPermission('superuser_security_view');
@@ -131,6 +143,7 @@ class superuserSecurityRoute
]);
$this->patch('/superuser/system/security/incidents/{id}', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/system/security/incidents/{id}');
global $response;
$this->requireClassicSuperuserPermission('superuser_security_incidents_manage');
@@ -148,6 +161,7 @@ class superuserSecurityRoute
]);
$this->post('/superuser/system/security/incidents/{id}/notes', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/superuser/system/security/incidents/{id}/notes');
global $response;
$this->requireClassicSuperuserPermission('superuser_security_incidents_manage');
@@ -5,6 +5,9 @@ namespace routes;
use classes\superuser_system_status_service;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class superuserSystemStatusRoute
{
use route_t;
@@ -12,6 +15,7 @@ class superuserSystemStatusRoute
public function run(): void
{
$this->get('/superuser/system/status', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/system/status');
global $response;
$this->requirePermission('superuser_system_status_view');
@@ -23,6 +27,7 @@ class superuserSystemStatusRoute
]);
$this->get('/superuser/system/database/status', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/system/database/status');
global $response;
$this->requirePermission('superuser_system_status_view');
@@ -10,6 +10,9 @@ use classes\system_search_service;
use Throwable;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class systemSearchRoute
{
use route_t;
@@ -17,14 +20,17 @@ class systemSearchRoute
public function run(): void
{
$this->get('/search/system', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/search/system');
$this->handleSearchRequest();
});
$this->post('/search/system', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/search/system');
$this->handleSearchRequest();
});
$this->delete('/superuser/search/system/cache', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/search/system/cache');
global /** @var response $response */
$response;
$this->requirePermission('superuser_search_system_cache_clear');
@@ -39,6 +45,7 @@ class systemSearchRoute
]);
$this->post('/superuser/search/system/cache/rebuild', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/superuser/search/system/cache/rebuild');
global /** @var response $response */
$response;
$this->requirePermission('superuser_search_system_cache_rebuild');
@@ -8,6 +8,9 @@ use classes\upload_store;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class uploadRoute
{
@@ -23,6 +26,7 @@ class uploadRoute
public function run(): void
{
$this->post('/upload/image', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/upload/image');
global $response;
// Get the uploaded file
$file = $_FILES['file'] ?? null;
@@ -50,6 +54,7 @@ class uploadRoute
$response->success($uploads->getPresignedUrl($objectKey));
});
$this->get('/openai/test', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/openai/test');
global $response;
// Validate the input parameters
// Example image URL for testing
@@ -7,6 +7,9 @@ use objects\collected_order_invoices_o;
use objects\logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class userInvoicesRoute
{
use route_t;
@@ -14,6 +17,7 @@ class userInvoicesRoute
public function run(): void
{
$this->get('/user/invoices', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/user/invoices');
// Require the user to be logged in
global $response;
$this->requirePermission('user_invoices');
@@ -46,6 +50,7 @@ class userInvoicesRoute
);
$this->put('/collected-invoices', function () {
ScopeMiddleware::requireScope(Scope::INVOICE_READ, '/collected-invoices');
// Require the user to be logged in
global $response;
$this->requirePermission('user_invoices');
@@ -7,6 +7,9 @@ use objects\logs_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class userNotificationsRoute
{
use route_t;
@@ -15,6 +18,7 @@ class userNotificationsRoute
{
$this->put('/account/notifications', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/account/notifications');
// Require the user to be logged in
global $response;
$this->requirePermission('user_notifications_update');
@@ -7,6 +7,9 @@ use objects\logs_o;
use objects\orders_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class userOrdersRoute
{
use route_t;
@@ -14,6 +17,7 @@ class userOrdersRoute
public function run(): void
{
$this->get('/user/orders', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/user/orders');
// Require the user to be logged in
global $response;
$this->requirePermission('list_own_orders');
@@ -48,6 +52,7 @@ class userOrdersRoute
);
$this->get('/user/order', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/user/order');
// Require the user to be logged in
global $response;
$this->requirePermission('fetch_own_order');
+11
View File
@@ -9,6 +9,9 @@ use objects\logs_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class userRoute
{
use route_t;
@@ -16,6 +19,7 @@ class userRoute
public function run(): void
{
$this->get('/superuser/user', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/superuser/user');
// Require the user to be logged in
global $response;
$this->requirePermission('get_user');
@@ -52,6 +56,7 @@ class userRoute
);
$this->get('/superuser/user/discounts', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/superuser/user/discounts');
// Require the user to be logged in
global $response;
$this->requirePermission('get_custom_prices_other');
@@ -86,6 +91,7 @@ class userRoute
);
$this->post('/superuser/user/discounts', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/superuser/user/discounts');
// Require the user to be logged in
global /** @var response $response */
$response;
@@ -204,6 +210,7 @@ class userRoute
);
$this->get('/admin/customer/getUserId', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/admin/customer/getUserId');
// Require the user to be logged in
global $response;
// Get the user object
@@ -250,6 +257,7 @@ class userRoute
);
$this->get('/admin/customer/name', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/admin/customer/name');
// Require the user to be logged in
global $response;
$this->requirePermission('get_user_name');
@@ -286,6 +294,7 @@ class userRoute
);
$this->get('/superuser/user/keys', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/superuser/user/keys');
// Require the user to be logged in
global $response;
$this->requirePermission('get_user_keys');
@@ -336,6 +345,7 @@ class userRoute
);
$this->post('/superuser/user/keys', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/superuser/user/keys');
// Require the user to be logged in
global $response;
$this->requirePermission('set_user_keys');
@@ -384,6 +394,7 @@ class userRoute
);
$this->post('/superuser/user/password', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/superuser/user/password');
// Require the user to be logged in
global $response;
$this->requirePermission('set_user_password');
@@ -7,6 +7,9 @@ use objects\logs_o;
use objects\tokens_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class userSecurityRoute
{
use route_t;
@@ -14,6 +17,7 @@ class userSecurityRoute
public function run(): void
{
$this->post('/account/security/change-email', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/account/security/change-email');
// Require the user to be logged in
global $response;
$this->requirePermission('user_security_change_email');
@@ -71,6 +75,7 @@ class userSecurityRoute
);
$this->post('/account/security/validate-password', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/account/security/validate-password');
// Require the user to be logged in
global $response;
$this->requirePermission('user_security_validate_password');
@@ -100,6 +105,7 @@ class userSecurityRoute
);
$this->post('/account/security/change-password', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/account/security/change-password');
// Require the user to be logged in
global $response;
$this->requirePermission('user_security_change_password');
@@ -140,6 +146,7 @@ class userSecurityRoute
);
$this->post('/account/security/change-phone-number', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/account/security/change-phone-number');
// Require the user to be logged in
global $response;
$this->requirePermission('user_security_change_phone_number');
+8
View File
@@ -8,6 +8,9 @@ use objects\logs_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class usersRoute
{
use route_t;
@@ -15,6 +18,7 @@ class usersRoute
public function run(): void
{
$this->get('/users', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/users');
// Require the user to be logged in
global /** @var response $response */
$response;
@@ -62,6 +66,7 @@ class usersRoute
);
$this->get('/users/customer', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/users/customer');
// Require the user to be logged in
global $response;
$this->requirePermission('get_user_from_customer_number');
@@ -95,6 +100,7 @@ class usersRoute
);
$this->post('/users', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/users');
// Require the user to be logged in
global $response;
$this->requirePermission('add_user');
@@ -149,6 +155,7 @@ class usersRoute
);
$this->put('/users', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/users');
// Require the user to be logged in
global $response;
$this->requirePermission('edit_user');
@@ -239,6 +246,7 @@ class usersRoute
);
$this->get('/public/employees', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/public/employees');
// This route is public, no authentication is required.
global $response;
// Get the users with the permission employee_public_data
@@ -7,6 +7,9 @@ use objects\customer_vehicles_addons_o;
use objects\customer_vehicles_o;
use objects\product_options_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
use modules\subusers\helpers\subusers_permission_node_key;
class vehicleAddonRoute
@@ -16,6 +19,7 @@ class vehicleAddonRoute
public function run(): void
{
$this->get('/vehicles/addons/available', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/vehicles/addons/available');
global $response;
$auth = new authentication();
$user = $auth->get_user();
@@ -81,6 +85,7 @@ class vehicleAddonRoute
);
$this->post('/vehicles/addons/toggle', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/vehicles/addons/toggle');
global $response;
$auth = new authentication();
$user = $auth->get_user();
@@ -16,6 +16,9 @@ use objects\plate_scans_o;
use objects\products_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
use modules\subusers\helpers\subusers_permission_node_key;
require_once WD . '/classes/security_policy_service.php';
@@ -346,6 +349,7 @@ class vehiclesRoute
public function run(): void
{
$this->get('/vehicles', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/vehicles');
global $response;
$auth = new authentication();
$user = $auth->get_user();
@@ -411,6 +415,7 @@ class vehiclesRoute
);
$this->get('/department/vehicles/unknown-customer', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/vehicles/unknown-customer');
// Require the user to be logged in
global $response;
$this->requirePermission('list_unknown_customer_vehicles');
@@ -442,6 +447,7 @@ class vehiclesRoute
);
$this->get('/superuser/users/{user_id}/vehicles', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/superuser/users/{user_id}/vehicles');
global $response;
$this->requirePermission('list_vehicles_other');
$targetUser = $this->resolveSuperuserVehicleTargetUser($this->routePositiveInt('user_id'));
@@ -452,6 +458,7 @@ class vehiclesRoute
]);
$this->get('/superuser/users/{user_id}/vehicles/summary', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/superuser/users/{user_id}/vehicles/summary');
global $response;
$this->requirePermission('list_vehicles_other');
$targetUser = $this->resolveSuperuserVehicleTargetUser($this->routePositiveInt('user_id'));
@@ -462,6 +469,7 @@ class vehiclesRoute
]);
$this->post('/superuser/users/{user_id}/vehicles', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/superuser/users/{user_id}/vehicles');
global $response;
$this->requirePermission('add_vehicle_other');
$targetUser = $this->resolveSuperuserVehicleTargetUser($this->routePositiveInt('user_id'));
@@ -472,6 +480,7 @@ class vehiclesRoute
]);
$this->put('/superuser/users/{user_id}/vehicles', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/superuser/users/{user_id}/vehicles');
global $response;
$this->requirePermission('edit_vehicle_other');
self::requireParameters(['id']);
@@ -487,6 +496,7 @@ class vehiclesRoute
]);
$this->delete('/superuser/users/{user_id}/vehicles', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/superuser/users/{user_id}/vehicles');
global $response;
$this->requirePermission('delete_vehicle_other');
self::requireParameters(['id']);
@@ -529,6 +539,7 @@ class vehiclesRoute
]);
$this->post('/vehicles', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/vehicles');
global $response;
$auth = new authentication();
$user = $auth->get_user();
@@ -626,6 +637,7 @@ class vehiclesRoute
);
$this->put('/vehicles', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/vehicles');
global $response;
$auth = new authentication();
$user = $auth->get_user();
@@ -803,6 +815,7 @@ class vehiclesRoute
);
$this->delete('/vehicles', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/vehicles');
global $response;
$auth = new authentication();
$user = $auth->get_user();
@@ -861,6 +874,7 @@ class vehiclesRoute
);
$this->get('/department/vehicle/customer-suggestions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/department/vehicle/customer-suggestions');
// Require the user to be logged in
global $response;
$this->requirePermission('list_vehicle_customer_suggestions');
@@ -923,6 +937,7 @@ class vehiclesRoute
);
$this->post('/vehicles/set-auto-start-on-lpr', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/vehicles/set-auto-start-on-lpr');
global $response;
$auth = new authentication();
$user = $auth->get_user();
@@ -958,6 +973,7 @@ class vehiclesRoute
);
$this->post('/vehicles/set-vehicle-type-id', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_WRITE, '/vehicles/set-vehicle-type-id');
global $response;
$auth = new authentication();
$user = $auth->get_user();
@@ -1006,6 +1022,7 @@ class vehiclesRoute
$this->get('/superuser/users-with-vehicle-subscriptions', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/superuser/users-with-vehicle-subscriptions');
// Require the user to be logged in
global $response;
$this->requirePermission('list_users_with_vehicle_subscriptions');
@@ -1049,6 +1066,7 @@ class vehiclesRoute
);
$this->get('/vehicles/status', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/vehicles/status');
// Require the user to be logged in
global $response;
$this->requirePermission('view_vehicle_status');
@@ -1124,6 +1142,7 @@ class vehiclesRoute
);
$this->get('/vehicles/search', function () {
ScopeMiddleware::requireScope(Scope::CUSTOMER_READ, '/vehicles/search');
global $response;
$this->requirePermission('search_vehicles');
/**
@@ -8,6 +8,8 @@ use objects\logs_o;
use objects\order_bookings_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
/**
* Debug route for diagnosing wash certificate delivery failures.
@@ -31,6 +33,7 @@ class washCertificateDebugRoute
public function run(): void
{
$this->get('/debug/wash-certificates/diagnose', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/debug/wash-certificates/diagnose');
global $response, $DEBUG;
if (empty($DEBUG)) {
@@ -4,6 +4,9 @@ namespace routes;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class washCertificateRoute
{
use route_t;
@@ -12,6 +15,7 @@ class washCertificateRoute
{
/** All bookings */
$this->get('/modules/washcertificates', function () {
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/modules/washcertificates');
// Set the working directory to /modules/washcertificates,
// so the output directory is created in the correct location
chdir(WD . '/modules/washcertificates');
@@ -18,6 +18,8 @@ use objects\product_options_o;
use objects\products_o;
use objects\users_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class workerRoute
{
@@ -26,6 +28,7 @@ class workerRoute
public function run(): void
{
$this->get('/worker/version', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/worker/version');
global /** @var router $router */
$response, $router;
$response->success(['version' => redis->get('worker_target_version') ?? 'unknown'] );
@@ -9,6 +9,9 @@ use objects\orders_o;
use objects\xlvask_usage_logs_o;
use traits\route_t;
use app\auth\Scope;
use app\auth\ScopeMiddleware;
class xlvaskUsageLogsRoute
{
use route_t;
@@ -16,6 +19,7 @@ class xlvaskUsageLogsRoute
public function run(): void
{
$this->get('/modules/xlvask/services/usage/orders', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/xlvask/services/usage/orders');
$permission_list_own = 'list_xlvask_usage_orders_own';
$permission_list_all = 'list_xlvask_usage_orders_all';
$response_includes_items = false;
@@ -122,6 +126,7 @@ class xlvaskUsageLogsRoute
]);
$this->get('/modules/xlvask/services/usage/orders/summary', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/xlvask/services/usage/orders/summary');
global $response;
if (!$this->hasPermission('list_xlvask_usage_orders_all')) {
$this->requirePermission('list_xlvask_usage_orders_own');
@@ -145,6 +150,7 @@ class xlvaskUsageLogsRoute
]);
$this->patch('/modules/xlvask/services/usage/orders/{id}/ignore', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/xlvask/services/usage/orders/{id}/ignore');
global $response;
$this->requirePermission('review_xlvask_usage_order');
$user = (new authentication())->get_user();
@@ -182,6 +188,7 @@ class xlvaskUsageLogsRoute
]);
$this->post('/modules/xlvask/services/usage/orders/{id}/unignore', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/xlvask/services/usage/orders/{id}/unignore');
global $response;
$this->requirePermission('review_xlvask_usage_order');
$user = (new authentication())->get_user();
@@ -209,6 +216,7 @@ class xlvaskUsageLogsRoute
]);
$this->post('/modules/xlvask/services/usage/orders/{id}/accept', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/xlvask/services/usage/orders/{id}/accept');
global $response;
$this->requirePermission('review_xlvask_usage_order');
$user = (new authentication())->get_user();
@@ -280,6 +288,7 @@ class xlvaskUsageLogsRoute
]);
$this->post('/modules/xlvask/services/usage/orders/{id}/reject', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_WRITE, '/modules/xlvask/services/usage/orders/{id}/reject');
global $response;
$this->requirePermission('review_xlvask_usage_order');
$user = (new authentication())->get_user();
@@ -317,6 +326,7 @@ class xlvaskUsageLogsRoute
]);
$this->get('/modules/xlvask/services/usage/orders/fast-link', function () {
ScopeMiddleware::requireScope(Scope::SUPERUSER_READ, '/modules/xlvask/services/usage/orders/fast-link');
global $response;
$this->requirePermission('list_xlvask_usage_orders_own');
$user = (new authentication())->get_user();
@@ -0,0 +1,212 @@
<?php
use app\auth\Scope;
use app\auth\ScopeMiddleware;
/*
* Integration tests for the route-scope wiring.
*
* The goal isn't to HTTP-test every route (that would need a live DB
* and a session token), it's to confirm:
*
* 1. Every documented route group has its `use app\auth\ScopeMiddleware`
* statement injected correctly.
* 2. Each route group's first non-public route guards the right scope.
* 3. Public routes (auth, ping, vehicle plate lookups, etc.) do
* NOT carry a scope check.
* 4. The middleware survives round-trips through the real
* response stub used by the route handlers.
* 5. Adding/removing a route's scope doesn't break the rest of
* the file's parsing.
*/
beforeEach(function (): void {
$GLOBALS['response'] = make_stub_response();
ScopeMiddleware::setTestPrincipal(null);
});
it('every protected route file imports the scope classes', function (): void {
$files = collect_protected_route_files();
expect($files)->not->toBeEmpty();
foreach ($files as $f) {
$src = file_get_contents($f);
expect($src)->toContain('use app\\auth\\ScopeMiddleware;');
expect($src)->toContain('use app\\auth\\Scope;');
}
});
it('every protected route file contains at least one requireScope() call', function (): void {
$files = collect_protected_route_files();
foreach ($files as $f) {
$src = file_get_contents($f);
$count = substr_count($src, 'ScopeMiddleware::requireScope');
expect($count)->toBeGreaterThan(0, "no requireScope() call in $f");
}
});
it('BrandingRoute is mixed (some public, some admin) and is excluded from the auto-list', function (): void {
// BrandingRoute has a public GET /branding and a private POST /branding
// variant. It doesn't fit the "all routes need a scope" rule, so
// the helper explicitly drops it. This test documents the
// exception so a future reader doesn't think the helper is wrong.
$files = collect_protected_route_files();
foreach ($files as $f) {
expect(basename($f))->not->toBe('BrandingRoute.php');
}
});
it('public route files do not require a scope', function (): void {
$public = [
'authRoute.php',
'pingRoute.php',
'optionsRoute.php',
'formRoute.php',
'guestRoute.php',
'errorReportRoute.php',
'vehiclePlateLookupRoute.php',
'vehiclePlateLastOrdersRoute.php',
'vehicleProductSuggestionRoute.php',
'callbackMicrosoftRoute.php',
'birdVoiceWebhooksRoute.php',
];
foreach ($public as $f) {
$path = app_path("routes/$f");
if (!file_exists($path)) {
// some don't exist in this checkout — fine
continue;
}
$src = file_get_contents($path);
expect(substr_count($src, 'ScopeMiddleware::requireScope'))
->toBe(0, "public route $f should not have scope checks");
}
});
it('the cron routes require SUPERUSER_READ on GET and SUPERUSER_WRITE on writes', function (): void {
$src = file_get_contents(app_path('routes/cronRoute.php'));
// GET /superuser/cron (list view) must require SUPERUSER_READ
$patternGet = '/\$this->get\(\'\/superuser\/cron\'[^,]*,\s*function[^{]*\{[^{]*requireScope\(\s*Scope::SUPERUSER_READ/';
$patternPost = '/\$this->post\(\'\/superuser\/cron\/run\'[^,]*,\s*function[^{]*\{[^{]*requireScope\(\s*Scope::SUPERUSER_WRITE/';
expect($src)->toMatch($patternGet);
expect($src)->toMatch($patternPost);
});
it('the bookings routes require BOOKING_READ on GET and BOOKING_WRITE on writes', function (): void {
$src = file_get_contents(app_path('routes/bookingsRoute.php'));
$patternGet = '/\$this->get\(\'\/bookings\'[^,]*,\s*function[^{]*\{[^{]*requireScope\(\s*Scope::BOOKING_READ/';
$patternPut = '/\$this->put\(\'\/bookings\'[^,]*,\s*function[^{]*\{[^{]*requireScope\(\s*Scope::BOOKING_WRITE/';
expect($src)->toMatch($patternGet);
expect($src)->toMatch($patternPut);
});
it('the invoice routes require INVOICE_READ on GET and INVOICE_WRITE on writes', function (): void {
$src = file_get_contents(app_path('routes/invoicesRoute.php'));
$patternGet = '/\$this->get\(\'\/invoices\/draft\'[^,]*,\s*function[^{]*\{[^{]*requireScope\(\s*Scope::INVOICE_READ/';
$patternPost = '/\$this->post\(\'\/invoices\/draft\/close\'[^,]*,\s*function[^{]*\{[^{]*requireScope\(\s*Scope::INVOICE_WRITE/';
expect($src)->toMatch($patternGet);
expect($src)->toMatch($patternPost);
});
it('the subuser routes require SUBUSER_READ and SUBUSER_WRITE', function (): void {
$src = file_get_contents(app_path('routes/subusersRoute.php'));
expect($src)->toMatch('/requireScope\\(\\s*Scope::SUBUSER_READ/');
expect($src)->toMatch('/requireScope\\(\\s*Scope::SUBUSER_WRITE/');
});
it('end-to-end: GET /bookings with no scope returns 403 via the middleware', function (): void {
// Anonymous principal, anonymous response stub.
ScopeMiddleware::setTestPrincipal(null);
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/bookings');
$resp = $GLOBALS['response'];
expect($resp->last_status)->toBe(403);
expect($resp->last_error)->toContain('Missing required scope');
});
it('end-to-end: GET /bookings with BOOKING_READ passes', function (): void {
ScopeMiddleware::setTestPrincipal([Scope::BOOKING_READ]);
ScopeMiddleware::requireScope(Scope::BOOKING_READ, '/bookings');
// No exception, response not modified.
$resp = $GLOBALS['response'];
expect($resp->last_status)->toBeNull();
});
it('end-to-end: POST /admin/bookings/sync requires BOOKING_WRITE', function (): void {
ScopeMiddleware::setTestPrincipal([Scope::BOOKING_READ]);
ScopeMiddleware::requireScope(Scope::BOOKING_WRITE, '/admin/bookings/sync');
$resp = $GLOBALS['response'];
expect($resp->last_status)->toBe(403);
});
it('end-to-end: superuser scope passes every scope check', function (): void {
ScopeMiddleware::setTestPrincipal(Scope::forRole('superuser'));
foreach ([Scope::BOOKING_READ, Scope::BOOKING_WRITE, Scope::INVOICE_WRITE,
Scope::SUBUSER_READ, Scope::CUSTOMER_WRITE, Scope::SUPERUSER_READ] as $s) {
ScopeMiddleware::requireScope($s, '/test');
}
expect($GLOBALS['response']->last_status)->toBeNull();
});
it('the audit documentation exists and covers the scope system', function (): void {
// The audit doc lives at the repo root, several levels up from
// this test. Walk up until we find it.
$candidates = [
__DIR__ . '/../../../../documentation/auth/route-scope-audit.md',
__DIR__ . '/../../../../../documentation/auth/route-scope-audit.md',
__DIR__ . '/../../../../../../documentation/auth/route-scope-audit.md',
];
$abs = false;
foreach ($candidates as $c) {
if (file_exists($c)) {
$abs = $c;
break;
}
}
expect($abs)->not->toBeFalse('audit doc missing — checked: ' . implode(', ', $candidates));
$src = file_get_contents($abs);
expect($src)->toContain('Scope::CUSTOMER_READ');
expect($src)->toContain('Scope::SUPERUSER_WRITE');
expect($src)->toContain('TRU-149');
});
// --- Test helpers --------------------------------------------------------
function collect_protected_route_files(): array
{
$base = app_path('routes');
$protected = [];
foreach (scandir($base) ?: [] as $f) {
if (!str_ends_with($f, '.php')) continue;
$src = file_get_contents("$base/$f");
if (!str_contains($src, '->get(') && !str_contains($src, '->post(') && !str_contains($src, '->put(') && !str_contains($src, '->delete(') && !str_contains($src, '->patch(')) {
continue;
}
if (str_contains($src, 'require_once') && !str_contains($src, 'use traits\\route_t;')) {
// stub file
continue;
}
// Public routes that we explicitly skip
$public = ['authRoute.php', 'pingRoute.php', 'optionsRoute.php', 'formRoute.php',
'guestRoute.php', 'errorReportRoute.php', 'callbackMicrosoftRoute.php',
'birdVoiceWebhooksRoute.php', 'vehiclePlateLookupRoute.php',
'vehiclePlateLastOrdersRoute.php', 'vehicleProductSuggestionRoute.php',
'permissionsRoute.php', 'rolesRoute.php', 'BrandingRoute.php'];
if (in_array($f, $public, true)) {
continue;
}
$protected[] = "$base/$f";
}
return $protected;
}
function make_stub_response(): object
{
return new class {
public ?int $last_status = null;
public ?string $last_error = null;
public function error(mixed $data, ?int $status = null): void
{
$this->last_status = $status ?? 500;
$this->last_error = is_string($data) ? $data : (string)json_encode($data);
}
};
}

Some files were not shown because too many files have changed in this diff Show More