@fleetbase/fleetops-engine 0.6.69 → 0.6.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/RELEASE.md +41 -8
  2. package/addon/components/admin/telematics-settings.hbs +143 -0
  3. package/addon/components/admin/telematics-settings.js +145 -0
  4. package/addon/components/fuel-integration/hub.hbs +1 -1
  5. package/addon/components/layout/fleet-ops-sidebar.js +37 -17
  6. package/addon/components/map/leaflet-live-map.hbs +4 -242
  7. package/addon/components/map/leaflet-live-map.js +2 -1
  8. package/addon/components/map/marker-card/driver.hbs +57 -0
  9. package/addon/components/map/marker-card/driver.js +3 -0
  10. package/addon/components/map/marker-card/vehicle.hbs +78 -0
  11. package/addon/components/map/marker-card/vehicle.js +3 -0
  12. package/addon/components/telematic/hub.hbs +1 -1
  13. package/addon/components/widget/live-fleet.hbs +8 -40
  14. package/addon/controllers/analytics/reports/index.js +5 -0
  15. package/addon/controllers/connectivity/devices/index.js +4 -0
  16. package/addon/controllers/connectivity/fuel-providers/index.js +6 -4
  17. package/addon/controllers/connectivity/sensors/index.js +4 -0
  18. package/addon/controllers/connectivity/telematics/index.js +4 -0
  19. package/addon/controllers/maintenance/equipment/index.js +11 -4
  20. package/addon/controllers/maintenance/inspection-forms/index.js +2 -2
  21. package/addon/controllers/maintenance/inspection-submissions/index.js +8 -2
  22. package/addon/controllers/maintenance/maintenances/index.js +4 -0
  23. package/addon/controllers/maintenance/parts/index.js +11 -4
  24. package/addon/controllers/maintenance/schedules/index.js +17 -4
  25. package/addon/controllers/maintenance/work-orders/index.js +11 -4
  26. package/addon/controllers/management/contacts/index.js +4 -0
  27. package/addon/controllers/management/drivers/index.js +4 -0
  28. package/addon/controllers/management/fleets/index.js +4 -0
  29. package/addon/controllers/management/fuel-reports/index.js +4 -0
  30. package/addon/controllers/management/fuel-transactions/index.js +9 -7
  31. package/addon/controllers/management/issues/index.js +4 -0
  32. package/addon/controllers/management/places/index.js +4 -0
  33. package/addon/controllers/management/vehicles/index.js +4 -0
  34. package/addon/controllers/management/vendors/index.js +4 -0
  35. package/addon/controllers/operations/orders/index/details.js +30 -1
  36. package/addon/controllers/operations/orders/index.js +7 -0
  37. package/addon/controllers/operations/service-rates/index.js +3 -0
  38. package/addon/controllers/settings/index.js +13 -0
  39. package/addon/controllers/settings/telematics.js +113 -0
  40. package/addon/extension.js +38 -6
  41. package/addon/routes/analytics/index.js +14 -1
  42. package/addon/routes/analytics/reports/index/details.js +1 -1
  43. package/addon/routes/analytics/reports/index/edit.js +1 -1
  44. package/addon/routes/analytics/reports/index/new.js +14 -1
  45. package/addon/routes/analytics/reports.js +14 -1
  46. package/addon/routes/connectivity/devices/index/new.js +14 -1
  47. package/addon/routes/connectivity/devices.js +14 -1
  48. package/addon/routes/connectivity/events.js +14 -1
  49. package/addon/routes/connectivity/fuel-providers/details/transactions.js +12 -0
  50. package/addon/routes/connectivity/fuel-providers/details.js +9 -0
  51. package/addon/routes/connectivity/fuel-providers/edit.js +9 -0
  52. package/addon/routes/connectivity/fuel-providers/new.js +14 -1
  53. package/addon/routes/connectivity/fuel-providers.js +14 -1
  54. package/addon/routes/connectivity/sensors/index/new.js +14 -1
  55. package/addon/routes/connectivity/sensors.js +14 -1
  56. package/addon/routes/connectivity/telematics/new.js +14 -1
  57. package/addon/routes/connectivity/telematics.js +14 -1
  58. package/addon/routes/connectivity/tracking.js +14 -1
  59. package/addon/routes/maintenance/equipment/index/details.js +2 -2
  60. package/addon/routes/maintenance/equipment/index/edit.js +2 -2
  61. package/addon/routes/maintenance/equipment/index/new.js +14 -1
  62. package/addon/routes/maintenance/equipment.js +14 -1
  63. package/addon/routes/maintenance/index.js +14 -1
  64. package/addon/routes/maintenance/inspection-forms/index/details.js +10 -1
  65. package/addon/routes/maintenance/inspection-forms/index/edit.js +10 -1
  66. package/addon/routes/maintenance/inspection-forms/index/new.js +14 -1
  67. package/addon/routes/maintenance/inspection-forms.js +14 -1
  68. package/addon/routes/maintenance/inspection-submissions/index/details.js +10 -1
  69. package/addon/routes/maintenance/inspection-submissions/index/edit.js +10 -1
  70. package/addon/routes/maintenance/inspection-submissions/index/new.js +14 -1
  71. package/addon/routes/maintenance/inspection-submissions.js +14 -1
  72. package/addon/routes/maintenance/maintenances/index/details.js +2 -2
  73. package/addon/routes/maintenance/maintenances/index/edit.js +2 -2
  74. package/addon/routes/maintenance/maintenances/index/new.js +14 -1
  75. package/addon/routes/maintenance/maintenances.js +14 -1
  76. package/addon/routes/maintenance/parts/index/details.js +2 -2
  77. package/addon/routes/maintenance/parts/index/edit.js +2 -2
  78. package/addon/routes/maintenance/parts/index/new.js +14 -1
  79. package/addon/routes/maintenance/parts.js +14 -1
  80. package/addon/routes/maintenance/schedules/index/details.js +2 -2
  81. package/addon/routes/maintenance/schedules/index/edit.js +2 -2
  82. package/addon/routes/maintenance/schedules/index/new.js +15 -1
  83. package/addon/routes/maintenance/schedules.js +15 -1
  84. package/addon/routes/maintenance/work-orders/index/details.js +2 -2
  85. package/addon/routes/maintenance/work-orders/index/edit.js +2 -2
  86. package/addon/routes/maintenance/work-orders/index/new.js +14 -1
  87. package/addon/routes/maintenance/work-orders.js +14 -1
  88. package/addon/routes/management/fuel-transactions/index/details.js +9 -0
  89. package/addon/routes/management/fuel-transactions.js +14 -1
  90. package/addon/routes/management/index.js +13 -0
  91. package/addon/routes/management/trailers.js +16 -0
  92. package/addon/routes/management/vendors/integrated/details.js +14 -1
  93. package/addon/routes/management/vendors/integrated/edit.js +14 -1
  94. package/addon/routes/management/vendors/integrated/new.js +14 -1
  95. package/addon/routes/management/vendors/integrated.js +14 -1
  96. package/addon/routes/operations/orders.js +40 -1
  97. package/addon/routes/operations/routes/index/details.js +14 -1
  98. package/addon/routes/operations/routes/index/new.js +13 -0
  99. package/addon/routes/operations/routes.js +14 -1
  100. package/addon/routes/operations/service-rates/index/new.js +11 -0
  101. package/addon/routes/operations/service-rates.js +14 -1
  102. package/addon/routes/settings/avatars.js +14 -1
  103. package/addon/routes/settings/custom-fields.js +14 -1
  104. package/addon/routes/settings/map.js +14 -1
  105. package/addon/routes/settings/notifications.js +11 -0
  106. package/addon/routes/settings/orchestrator.js +1 -1
  107. package/addon/routes/settings/payments/index.js +1 -1
  108. package/addon/routes/settings/routing.js +14 -1
  109. package/addon/routes/settings/scheduling.js +14 -1
  110. package/addon/routes/settings/telematics.js +21 -0
  111. package/addon/routes/virtual.js +11 -0
  112. package/addon/routes.js +1 -0
  113. package/addon/templates/settings/telematics.hbs +70 -0
  114. package/app/components/admin/telematics-settings.js +1 -0
  115. package/app/components/map/marker-card/driver.js +1 -0
  116. package/app/components/map/marker-card/vehicle.js +1 -0
  117. package/app/controllers/settings/telematics.js +1 -0
  118. package/app/routes/settings/telematics.js +1 -0
  119. package/app/templates/settings/telematics.js +1 -0
  120. package/composer.json +2 -2
  121. package/docs/AFAQY.md +1 -1
  122. package/docs/TELEMATICS_QUEUES.md +1 -1
  123. package/docs/TELEMETRY_ARCHITECTURE.md +72 -1
  124. package/extension.json +1 -1
  125. package/package.json +1 -1
  126. package/server/config/telemetry.php +12 -0
  127. package/server/migrations/2026_09_23_000001_add_retention_index_to_device_events.php +40 -0
  128. package/server/migrations/2026_09_23_000002_add_retention_index_to_positions.php +40 -0
  129. package/server/migrations/2026_09_23_000003_add_retention_index_to_telematic_sync_runs.php +40 -0
  130. package/server/src/Auth/Schemas/FleetOps.php +104 -5
  131. package/server/src/Console/Commands/DrainTelematicInbox.php +3 -13
  132. package/server/src/Console/Commands/ProcessOperationalAlerts.php +3 -3
  133. package/server/src/Console/Commands/PruneTelematicsData.php +318 -0
  134. package/server/src/Http/Controllers/Api/v1/OrchestrationController.php +9 -0
  135. package/server/src/Http/Controllers/FleetOpsController.php +21 -0
  136. package/server/src/Http/Controllers/Internal/v1/AnalyticsController.php +11 -0
  137. package/server/src/Http/Controllers/Internal/v1/ContactController.php +11 -0
  138. package/server/src/Http/Controllers/Internal/v1/CustomerController.php +14 -0
  139. package/server/src/Http/Controllers/Internal/v1/DeviceController.php +13 -0
  140. package/server/src/Http/Controllers/Internal/v1/DeviceEventController.php +11 -0
  141. package/server/src/Http/Controllers/Internal/v1/DriverController.php +22 -0
  142. package/server/src/Http/Controllers/Internal/v1/FuelProviderConnectionController.php +13 -0
  143. package/server/src/Http/Controllers/Internal/v1/FuelProviderTransactionController.php +15 -0
  144. package/server/src/Http/Controllers/Internal/v1/FuelReportController.php +9 -3
  145. package/server/src/Http/Controllers/Internal/v1/InspectionFormController.php +15 -0
  146. package/server/src/Http/Controllers/Internal/v1/LiveController.php +16 -0
  147. package/server/src/Http/Controllers/Internal/v1/MaintenanceController.php +15 -0
  148. package/server/src/Http/Controllers/Internal/v1/MaintenanceScheduleController.php +15 -0
  149. package/server/src/Http/Controllers/Internal/v1/ManifestController.php +15 -0
  150. package/server/src/Http/Controllers/Internal/v1/MetricsController.php +11 -0
  151. package/server/src/Http/Controllers/Internal/v1/NavigatorController.php +42 -1
  152. package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +12 -0
  153. package/server/src/Http/Controllers/Internal/v1/OrderController.php +22 -0
  154. package/server/src/Http/Controllers/Internal/v1/PaymentController.php +13 -0
  155. package/server/src/Http/Controllers/Internal/v1/RadarController.php +19 -0
  156. package/server/src/Http/Controllers/Internal/v1/ServiceAreaController.php +9 -3
  157. package/server/src/Http/Controllers/Internal/v1/SettingController.php +465 -14
  158. package/server/src/Http/Controllers/Internal/v1/TelematicController.php +21 -0
  159. package/server/src/Http/Controllers/Internal/v1/TrailerController.php +21 -0
  160. package/server/src/Http/Controllers/Internal/v1/VehicleController.php +21 -0
  161. package/server/src/Http/Controllers/Internal/v1/VendorController.php +17 -0
  162. package/server/src/Http/Controllers/Internal/v1/WorkOrderController.php +11 -0
  163. package/server/src/Jobs/DispatchTelematicsRetentionJobs.php +70 -0
  164. package/server/src/Jobs/PruneTelematicsDataJob.php +74 -0
  165. package/server/src/Listeners/NotifyDriverOnShiftChange.php +3 -3
  166. package/server/src/Mail/CustomerCredentialsMail.php +1 -1
  167. package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +9 -1
  168. package/server/src/Providers/FleetOpsServiceProvider.php +3 -0
  169. package/server/src/Support/Analytics/LiveFleet.php +18 -2
  170. package/server/src/Support/Authorization.php +103 -0
  171. package/server/src/Support/Database/TableIndexes.php +66 -0
  172. package/server/src/Support/OrderTracker.php +2 -2
  173. package/server/src/Support/Reporting/FleetOpsReportSchema.php +476 -116
  174. package/server/src/Support/Telematics/Retention/RetentionPolicy.php +300 -0
  175. package/server/src/Support/Telematics/Retention/TelemetryActivity.php +40 -0
  176. package/server/src/Support/Telematics/TelematicService.php +12 -2
  177. package/server/src/Support/Telematics/Telemetry/Ingestor.php +4 -2
  178. package/server/src/Tracking/TrackingIntelligenceService.php +1 -1
  179. package/server/src/Tracking/TrackingOptions.php +2 -2
  180. package/server/src/Traits/AuthorizesMethods.php +37 -0
  181. package/server/src/routes.php +9 -1
  182. package/server/tests/AnalyticsRoutesTest.php +29 -2
  183. package/server/tests/Feature/Http/AfaqyRealtimeIngestionTest.php +16 -1
  184. package/server/tests/Feature/Http/Api/TelematicsRetentionIndexMigrationTest.php +115 -0
  185. package/server/tests/Feature/Http/Internal/SettingControllerHelpersTest.php +71 -0
  186. package/server/tests/Feature/Http/Internal/TelematicsStorageDeadlinesTest.php +119 -0
  187. package/server/tests/InternalImportExportControllerContractsTest.php +5 -8
  188. package/server/tests/NavigatorControllerContractsTest.php +36 -4
  189. package/server/tests/NotificationAndMailContractsTest.php +31 -0
  190. package/server/tests/ObserverContractsTest.php +1 -1
  191. package/server/tests/OrchestratorConsumableApiTest.php +42 -0
  192. package/server/tests/ProviderContractsTest.php +10 -0
  193. package/server/tests/ReportSchemaContractsTest.php +120 -6
  194. package/server/tests/SettingControllerContractsTest.php +429 -18
  195. package/server/tests/SmallControllerContractsTest.php +8 -5
  196. package/server/tests/Support/PruneTelematicsDataProbe.php +55 -0
  197. package/server/tests/Unit/Console/Commands/ProcessOperationalAlertsCommandTest.php +2 -2
  198. package/server/tests/Unit/Console/PruneTelematicsDataCommandTest.php +353 -0
  199. package/server/tests/Unit/Jobs/DispatchTelematicsRetentionJobsTest.php +114 -0
  200. package/server/tests/Unit/Jobs/PruneTelematicsDataJobTest.php +60 -0
  201. package/server/tests/Unit/Orchestration/VroomEngineTransportAndSettingsTest.php +20 -0
  202. package/server/tests/Unit/Support/Analytics/LiveFleetTest.php +6 -0
  203. package/server/tests/Unit/Support/AuthorizationTest.php +142 -0
  204. package/server/tests/Unit/Support/MaintainableAndOperationalAlertsTest.php +12 -1
  205. package/server/tests/Unit/Support/MoreQuerySeamsTest.php +11 -2
  206. package/server/tests/Unit/Support/Telematics/Retention/RetentionPolicyTest.php +190 -0
  207. package/server/tests/Unit/Support/Telematics/Retention/TelemetryActivityTest.php +68 -0
  208. package/server/tests/Unit/Tracking/TrackingOptionsCompanySettingsTest.php +109 -0
  209. package/translations/en-us.yaml +48 -0
@@ -2,6 +2,7 @@
2
2
 
3
3
  namespace Fleetbase\FleetOps\Http\Controllers\Internal\v1;
4
4
 
5
+ use Fleetbase\Attributes\SkipAuthorizationCheck;
5
6
  use Fleetbase\FleetOps\Http\Controllers\FleetOpsController;
6
7
  use Fleetbase\FleetOps\Models\FuelProviderTransaction;
7
8
  use Fleetbase\FleetOps\Support\FuelProviders\FuelProviderService;
@@ -10,6 +11,17 @@ use Illuminate\Http\Request;
10
11
 
11
12
  class FuelProviderTransactionController extends FleetOpsController
12
13
  {
14
+ /**
15
+ * Permissions for methods AuthorizationGuard cannot map to a schema action (see FleetOpsController).
16
+ *
17
+ * @var array<string, string|string[]>
18
+ */
19
+ protected array $methodPermissions = [
20
+ 'matchVehicle' => 'update fuel-provider-transaction',
21
+ 'matchOrder' => 'update fuel-provider-transaction',
22
+ 'reprocess' => 'update fuel-provider-transaction',
23
+ ];
24
+
13
25
  public $resource = 'fuel_provider_transaction';
14
26
 
15
27
  public function __construct(protected FuelProviderService $fuelProviderService)
@@ -22,6 +34,7 @@ class FuelProviderTransactionController extends FleetOpsController
22
34
  $query->with(['vehicle', 'driver', 'fuelReport']);
23
35
  }
24
36
 
37
+ #[SkipAuthorizationCheck]
25
38
  public function matchVehicle(Request $request, string $id): JsonResponse
26
39
  {
27
40
  $request->validate(['vehicle' => 'required|string']);
@@ -33,6 +46,7 @@ class FuelProviderTransactionController extends FleetOpsController
33
46
  ]);
34
47
  }
35
48
 
49
+ #[SkipAuthorizationCheck]
36
50
  public function matchOrder(Request $request, string $id): JsonResponse
37
51
  {
38
52
  $request->validate(['order' => 'required|string']);
@@ -44,6 +58,7 @@ class FuelProviderTransactionController extends FleetOpsController
44
58
  ]);
45
59
  }
46
60
 
61
+ #[SkipAuthorizationCheck]
47
62
  public function reprocess(Request $request, string $id): JsonResponse
48
63
  {
49
64
  $transaction = $this->findTransaction($id);
@@ -9,6 +9,7 @@ use Fleetbase\FleetOps\Models\FuelReport;
9
9
  use Fleetbase\Http\Requests\ExportRequest;
10
10
  use Fleetbase\Http\Requests\ImportRequest;
11
11
  use Illuminate\Http\Request;
12
+ use Illuminate\Support\Arr;
12
13
  use Illuminate\Support\Str;
13
14
  use Maatwebsite\Excel\Facades\Excel;
14
15
 
@@ -23,11 +24,16 @@ class FuelReportController extends FleetOpsController
23
24
 
24
25
  /**
25
26
  * Handle post save transactions.
27
+ *
28
+ * Reads the custom field values from the payload the base controller already extracted
29
+ * rather than from the raw request: Ember Data sends the resource under a camelCase root
30
+ * (`fuelReport`), so `$request->array('fuel_report.custom_field_values')` was always empty and no
31
+ * custom field value was ever persisted for this resource.
26
32
  */
27
- public function afterSave(Request $request, FuelReport $fuelReport)
33
+ public function afterSave(Request $request, FuelReport $fuelReport, array $input = [])
28
34
  {
29
- $customFieldValues = $request->array('fuel_report.custom_field_values');
30
- if ($customFieldValues) {
35
+ $customFieldValues = Arr::get($input, 'custom_field_values');
36
+ if (is_array($customFieldValues) && $customFieldValues) {
31
37
  $fuelReport->syncCustomFieldValues($customFieldValues);
32
38
  }
33
39
  }
@@ -2,6 +2,7 @@
2
2
 
3
3
  namespace Fleetbase\FleetOps\Http\Controllers\Internal\v1;
4
4
 
5
+ use Fleetbase\Attributes\SkipAuthorizationCheck;
5
6
  use Fleetbase\FleetOps\Http\Controllers\FleetOpsController;
6
7
  use Fleetbase\FleetOps\Http\Resources\v1\InspectionLink as InspectionLinkResource;
7
8
  use Fleetbase\FleetOps\Models\Driver;
@@ -16,6 +17,17 @@ use Illuminate\Http\Request;
16
17
 
17
18
  class InspectionFormController extends FleetOpsController
18
19
  {
20
+ /**
21
+ * Permissions for methods AuthorizationGuard cannot map to a schema action (see FleetOpsController).
22
+ *
23
+ * @var array<string, string|string[]>
24
+ */
25
+ protected array $methodPermissions = [
26
+ 'generateLink' => 'publish inspection-form',
27
+ 'revokeLink' => 'publish inspection-form',
28
+ 'sendPin' => 'publish inspection-form',
29
+ ];
30
+
19
31
  /**
20
32
  * The resource to query.
21
33
  *
@@ -107,6 +119,7 @@ class InspectionFormController extends FleetOpsController
107
119
  ]);
108
120
  }
109
121
 
122
+ #[SkipAuthorizationCheck]
110
123
  public function generateLink(Request $request, string $id): JsonResponse
111
124
  {
112
125
  $form = $this->resolveForm($id)
@@ -215,6 +228,7 @@ class InspectionFormController extends FleetOpsController
215
228
  }
216
229
 
217
230
  /** Take a link out of use, leaving the record of it in the list. */
231
+ #[SkipAuthorizationCheck]
218
232
  public function revokeLink(Request $request, string $id, string $linkId): JsonResponse
219
233
  {
220
234
  $form = $this->resolveForm($id)->firstOrFail();
@@ -243,6 +257,7 @@ class InspectionFormController extends FleetOpsController
243
257
  * A failed delivery answers 200 with `pin_delivery.sent` false and why, so
244
258
  * the console shows it as a warning rather than an error.
245
259
  */
260
+ #[SkipAuthorizationCheck]
246
261
  public function sendPin(Request $request, string $id, string $linkId): JsonResponse
247
262
  {
248
263
  $form = $this->resolveForm($id)->firstOrFail();
@@ -18,6 +18,7 @@ use Fleetbase\FleetOps\Models\Vehicle;
18
18
  use Fleetbase\FleetOps\Support\LiveCacheService;
19
19
  use Fleetbase\FleetOps\Support\LiveOrderQuery;
20
20
  use Fleetbase\FleetOps\Support\Utils;
21
+ use Fleetbase\FleetOps\Traits\AuthorizesMethods;
21
22
  use Fleetbase\Http\Controllers\Controller;
22
23
  use Illuminate\Http\Request;
23
24
 
@@ -26,6 +27,21 @@ use Illuminate\Http\Request;
26
27
  */
27
28
  class LiveController extends Controller
28
29
  {
30
+ use AuthorizesMethods;
31
+
32
+ public function __construct()
33
+ {
34
+ $this->authorizeMethods([
35
+ 'coordinates' => 'list order',
36
+ 'routes' => 'list order',
37
+ 'orders' => 'list order',
38
+ 'drivers' => 'list driver',
39
+ 'vehicles' => 'list vehicle',
40
+ 'operationsMonitor' => 'list order',
41
+ 'places' => 'list place',
42
+ ]);
43
+ }
44
+
29
45
  protected const DEFAULT_VIEWPORT_LIMIT = 500;
30
46
  protected const MAX_VIEWPORT_LIMIT = 1000;
31
47
  protected const VIEWPORT_BOUNDS_PRECISION = 4;
@@ -2,6 +2,7 @@
2
2
 
3
3
  namespace Fleetbase\FleetOps\Http\Controllers\Internal\v1;
4
4
 
5
+ use Fleetbase\Attributes\SkipAuthorizationCheck;
5
6
  use Fleetbase\FleetOps\Exports\MaintenanceExport;
6
7
  use Fleetbase\FleetOps\Http\Controllers\FleetOpsController;
7
8
  use Fleetbase\FleetOps\Imports\MaintenanceImport;
@@ -15,6 +16,17 @@ use Maatwebsite\Excel\Facades\Excel;
15
16
 
16
17
  class MaintenanceController extends FleetOpsController
17
18
  {
19
+ /**
20
+ * Permissions for methods AuthorizationGuard cannot map to a schema action (see FleetOpsController).
21
+ *
22
+ * @var array<string, string|string[]>
23
+ */
24
+ protected array $methodPermissions = [
25
+ 'addLineItem' => 'update maintenance',
26
+ 'updateLineItem' => 'update maintenance',
27
+ 'removeLineItem' => 'update maintenance',
28
+ ];
29
+
18
30
  /**
19
31
  * The resource to query.
20
32
  *
@@ -67,6 +79,7 @@ class MaintenanceController extends FleetOpsController
67
79
  * Add a cost line item to a maintenance record.
68
80
  * POST /maintenances/{id}/line-items.
69
81
  */
82
+ #[SkipAuthorizationCheck]
70
83
  public function addLineItem(string $id, Request $request): JsonResponse
71
84
  {
72
85
  $maintenance = $this->findMaintenanceForLineItem($id);
@@ -89,6 +102,7 @@ class MaintenanceController extends FleetOpsController
89
102
  * Update a cost line item on a maintenance record.
90
103
  * PUT /maintenances/{id}/line-items/{index}.
91
104
  */
105
+ #[SkipAuthorizationCheck]
92
106
  public function updateLineItem(string $id, int $index, Request $request): JsonResponse
93
107
  {
94
108
  $maintenance = $this->findMaintenanceForLineItem($id);
@@ -121,6 +135,7 @@ class MaintenanceController extends FleetOpsController
121
135
  * Remove a cost line item from a maintenance record.
122
136
  * DELETE /maintenances/{id}/line-items/{index}.
123
137
  */
138
+ #[SkipAuthorizationCheck]
124
139
  public function removeLineItem(string $id, int $index): JsonResponse
125
140
  {
126
141
  $maintenance = $this->findMaintenanceForLineItem($id);
@@ -2,6 +2,7 @@
2
2
 
3
3
  namespace Fleetbase\FleetOps\Http\Controllers\Internal\v1;
4
4
 
5
+ use Fleetbase\Attributes\SkipAuthorizationCheck;
5
6
  use Fleetbase\FleetOps\Exports\MaintenanceScheduleExport;
6
7
  use Fleetbase\FleetOps\Http\Controllers\FleetOpsController;
7
8
  use Fleetbase\FleetOps\Imports\MaintenanceScheduleImport;
@@ -22,6 +23,17 @@ use Spatie\IcalendarGenerator\ValueObjects\RRule;
22
23
 
23
24
  class MaintenanceScheduleController extends FleetOpsController
24
25
  {
26
+ /**
27
+ * Permissions for methods AuthorizationGuard cannot map to a schema action (see FleetOpsController).
28
+ *
29
+ * @var array<string, string|string[]>
30
+ */
31
+ protected array $methodPermissions = [
32
+ 'pause' => 'update maintenance-schedule',
33
+ 'resume' => 'update maintenance-schedule',
34
+ 'trigger' => 'update maintenance-schedule',
35
+ ];
36
+
25
37
  /**
26
38
  * The resource to query.
27
39
  *
@@ -71,6 +83,7 @@ class MaintenanceScheduleController extends FleetOpsController
71
83
  * Pause a maintenance schedule.
72
84
  * POST /maintenance-schedules/{id}/pause.
73
85
  */
86
+ #[SkipAuthorizationCheck]
74
87
  public function pause(string $id): JsonResponse
75
88
  {
76
89
  $schedule = $this->findSchedule($id);
@@ -88,6 +101,7 @@ class MaintenanceScheduleController extends FleetOpsController
88
101
  * Resume a paused maintenance schedule.
89
102
  * POST /maintenance-schedules/{id}/resume.
90
103
  */
104
+ #[SkipAuthorizationCheck]
91
105
  public function resume(string $id): JsonResponse
92
106
  {
93
107
  $schedule = $this->findSchedule($id);
@@ -105,6 +119,7 @@ class MaintenanceScheduleController extends FleetOpsController
105
119
  * Manually trigger a work order from a schedule.
106
120
  * POST /maintenance-schedules/{id}/trigger.
107
121
  */
122
+ #[SkipAuthorizationCheck]
108
123
  public function trigger(string $id, Request $request): JsonResponse
109
124
  {
110
125
  $schedule = $this->findSchedule($id);
@@ -4,6 +4,7 @@ namespace Fleetbase\FleetOps\Http\Controllers\Internal\v1;
4
4
 
5
5
  use Fleetbase\FleetOps\Models\Manifest;
6
6
  use Fleetbase\FleetOps\Models\ManifestStop;
7
+ use Fleetbase\FleetOps\Traits\AuthorizesMethods;
7
8
  use Fleetbase\Http\Controllers\Controller;
8
9
  use Illuminate\Http\JsonResponse;
9
10
  use Illuminate\Http\Request;
@@ -23,6 +24,20 @@ use Illuminate\Http\Request;
23
24
  */
24
25
  class ManifestController extends Controller
25
26
  {
27
+ use AuthorizesMethods;
28
+
29
+ public function __construct()
30
+ {
31
+ $this->authorizeMethods([
32
+ 'index' => 'list order',
33
+ 'show' => 'view order',
34
+ 'cancel' => 'cancel order',
35
+ 'destroy' => 'delete order',
36
+ 'showStop' => 'view order',
37
+ 'updateStop' => 'update order',
38
+ ]);
39
+ }
40
+
26
41
  /**
27
42
  * List manifests for the current company.
28
43
  * Supports filtering by status, driver_id, vehicle_id, and scheduled_date.
@@ -2,6 +2,7 @@
2
2
 
3
3
  namespace Fleetbase\FleetOps\Http\Controllers\Internal\v1;
4
4
 
5
+ use Fleetbase\FleetOps\Support\Authorization;
5
6
  use Fleetbase\FleetOps\Support\Metrics;
6
7
  use Fleetbase\FleetOps\Support\Metrics\Registry;
7
8
  use Fleetbase\Http\Controllers\Controller;
@@ -10,6 +11,16 @@ use Illuminate\Support\Carbon;
10
11
 
11
12
  class MetricsController extends Controller
12
13
  {
14
+ public function __construct()
15
+ {
16
+ // Not a resource controller, so AuthorizationGuard cannot resolve a permission for it.
17
+ $this->middleware(function ($request, $next) {
18
+ Authorization::authorize('view analytics');
19
+
20
+ return $next($request);
21
+ });
22
+ }
23
+
13
24
  /**
14
25
  * Legacy bulk endpoint. Returns a flat map of slug → scalar value for the
15
26
  * requested period. Preserved for backward compat; the dashboard widgets
@@ -3,6 +3,7 @@
3
3
  namespace Fleetbase\FleetOps\Http\Controllers\Internal\v1;
4
4
 
5
5
  use Fleetbase\FleetOps\Support\Utils;
6
+ use Fleetbase\FleetOps\Traits\AuthorizesMethods;
6
7
  use Fleetbase\Http\Controllers\Controller;
7
8
  use Fleetbase\Http\Resources\Organization;
8
9
  use Fleetbase\Models\ApiCredential;
@@ -15,6 +16,19 @@ use Illuminate\Support\Str;
15
16
 
16
17
  class NavigatorController extends Controller
17
18
  {
19
+ use AuthorizesMethods;
20
+ /**
21
+ * How long a Navigator link issued from the console stays valid.
22
+ */
23
+ public const LINK_TTL_MINUTES = 30;
24
+
25
+ public function __construct()
26
+ {
27
+ $this->authorizeMethods([
28
+ 'getLinkAppUrl' => 'admin',
29
+ ]);
30
+ }
31
+
18
32
  /**
19
33
  * Redirects to the Fleetbase Navigator app using a deep link.
20
34
  * Automatically detects the platform (iOS or Android) and uses the correct URI scheme.
@@ -23,6 +37,12 @@ class NavigatorController extends Controller
23
37
  */
24
38
  public function linkApp(Request $request)
25
39
  {
40
+ // This route is opened from a phone without a console session, so it is
41
+ // authorised by the short-lived signature issued by getLinkAppUrl().
42
+ if (!$this->hasValidLinkSignature($request)) {
43
+ return response()->error('This Navigator link is invalid or has expired. Generate a new one from the console.', 403);
44
+ }
45
+
26
46
  $adminUser = $this->findAdminUser();
27
47
 
28
48
  if (!$adminUser || !$adminUser->company) {
@@ -67,8 +87,13 @@ class NavigatorController extends Controller
67
87
  */
68
88
  public function getLinkAppUrl()
69
89
  {
90
+ $expires = now()->addMinutes(static::LINK_TTL_MINUTES)->getTimestamp();
91
+
70
92
  return response()->json([
71
- 'linkUrl' => url('int/v1/fleet-ops/navigator/link-app'),
93
+ 'linkUrl' => url('int/v1/fleet-ops/navigator/link-app') . '?' . http_build_query([
94
+ 'expires' => $expires,
95
+ 'signature' => static::linkSignature($expires),
96
+ ]),
72
97
  ]);
73
98
  }
74
99
 
@@ -189,4 +214,20 @@ class NavigatorController extends Controller
189
214
  {
190
215
  return Setting::where('key', 'fleet-ops.driver-onboard')->value('value');
191
216
  }
217
+
218
+ /**
219
+ * HMAC signature for a Navigator link expiring at the given unix timestamp.
220
+ */
221
+ public static function linkSignature(int $expires): string
222
+ {
223
+ return hash_hmac('sha256', 'fleet-ops.navigator.link-app|' . $expires, (string) config('app.key'));
224
+ }
225
+
226
+ protected function hasValidLinkSignature(Request $request): bool
227
+ {
228
+ $expires = (int) $request->query('expires');
229
+ $signature = (string) $request->query('signature');
230
+
231
+ return $signature !== '' && $expires >= time() && hash_equals(static::linkSignature($expires), $signature);
232
+ }
192
233
  }
@@ -16,6 +16,7 @@ use Fleetbase\FleetOps\Models\Vendor;
16
16
  use Fleetbase\FleetOps\Orchestration\Engines\DriverAssignmentEngine;
17
17
  use Fleetbase\FleetOps\Orchestration\Engines\RouteSequencingEngine;
18
18
  use Fleetbase\FleetOps\Orchestration\OrchestrationEngineRegistry;
19
+ use Fleetbase\FleetOps\Traits\AuthorizesMethods;
19
20
  use Fleetbase\Http\Controllers\Controller;
20
21
  use Fleetbase\Models\Setting;
21
22
  use Illuminate\Http\JsonResponse;
@@ -39,8 +40,19 @@ use Illuminate\Support\Str;
39
40
  */
40
41
  class OrchestrationController extends Controller
41
42
  {
43
+ use AuthorizesMethods;
44
+
42
45
  public function __construct(protected OrchestrationEngineRegistry $registry)
43
46
  {
47
+ $this->authorizeMethods([
48
+ 'orders' => 'list order',
49
+ 'run' => 'optimize order',
50
+ 'preview' => 'list order',
51
+ 'commit' => 'assign-driver-for order',
52
+ 'engines' => 'list order',
53
+ 'orderConfigFields' => 'list order',
54
+ 'importOrders' => 'import order',
55
+ ]);
44
56
  }
45
57
 
46
58
  /**
@@ -2,6 +2,7 @@
2
2
 
3
3
  namespace Fleetbase\FleetOps\Http\Controllers\Internal\v1;
4
4
 
5
+ use Fleetbase\Attributes\SkipAuthorizationCheck;
5
6
  use Fleetbase\Exceptions\FleetbaseRequestValidationException;
6
7
  use Fleetbase\FleetOps\Events\EntityActivityChanged;
7
8
  use Fleetbase\FleetOps\Events\EntityCompleted;
@@ -53,6 +54,20 @@ use Maatwebsite\Excel\Facades\Excel;
53
54
  class OrderController extends FleetOpsController
54
55
  {
55
56
  use ResolvesOrderServiceStops;
57
+ /**
58
+ * Permissions for methods AuthorizationGuard cannot map to a schema action (see FleetOpsController).
59
+ *
60
+ * @var array<string, string|string[]>
61
+ */
62
+ protected array $methodPermissions = [
63
+ 'editOrderRoute' => 'update-route-for order',
64
+ 'importFromFiles' => 'import order',
65
+ 'bulkCancel' => 'cancel order',
66
+ 'bulkDispatch' => 'dispatch order',
67
+ 'bulkAssignDriver' => 'assign-driver-for order',
68
+ 'dispatchOrder' => 'dispatch order',
69
+ 'scheduleOrder' => 'schedule order',
70
+ ];
56
71
 
57
72
  /**
58
73
  * The resource to query.
@@ -267,6 +282,7 @@ class OrderController extends FleetOpsController
267
282
  *
268
283
  * @return Response
269
284
  */
285
+ #[SkipAuthorizationCheck]
270
286
  public function editOrderRoute(string $id, Request $request)
271
287
  {
272
288
  $pickup = $request->input('pickup');
@@ -337,6 +353,7 @@ class OrderController extends FleetOpsController
337
353
  *
338
354
  * @return \Illuminate\Http\Response
339
355
  */
356
+ #[SkipAuthorizationCheck]
340
357
  public function importFromFiles(Request $request)
341
358
  {
342
359
  $info = Utils::lookupIp();
@@ -409,6 +426,7 @@ class OrderController extends FleetOpsController
409
426
  *
410
427
  * @return \Illuminate\Http\Response
411
428
  */
429
+ #[SkipAuthorizationCheck]
412
430
  public function bulkCancel(Request $request)
413
431
  {
414
432
  $request->validate([
@@ -454,6 +472,7 @@ class OrderController extends FleetOpsController
454
472
  *
455
473
  * @return \Illuminate\Http\Response
456
474
  */
475
+ #[SkipAuthorizationCheck]
457
476
  public function bulkDispatch(BulkDispatchRequest $request)
458
477
  {
459
478
  /** @var Order */
@@ -502,6 +521,7 @@ class OrderController extends FleetOpsController
502
521
  *
503
522
  * @return \Illuminate\Http\Response
504
523
  */
524
+ #[SkipAuthorizationCheck]
505
525
  public function bulkAssignDriver(Request $request)
506
526
  {
507
527
  // Validate Inputs
@@ -578,6 +598,7 @@ class OrderController extends FleetOpsController
578
598
  *
579
599
  * @return \Illuminate\Http\Response
580
600
  */
601
+ #[SkipAuthorizationCheck]
581
602
  public function dispatchOrder(Request $request)
582
603
  {
583
604
  /**
@@ -1906,6 +1927,7 @@ class OrderController extends FleetOpsController
1906
1927
  *
1907
1928
  * @return \Illuminate\Http\Response
1908
1929
  */
1930
+ #[SkipAuthorizationCheck]
1909
1931
  public function scheduleOrder(Request $request)
1910
1932
  {
1911
1933
  $orderId = $request->input('order');
@@ -4,6 +4,7 @@ namespace Fleetbase\FleetOps\Http\Controllers\Internal\v1;
4
4
 
5
5
  use Fleetbase\FleetOps\Models\PurchaseRate;
6
6
  use Fleetbase\FleetOps\Support\Payment;
7
+ use Fleetbase\FleetOps\Traits\AuthorizesMethods;
7
8
  use Fleetbase\Http\Controllers\Controller;
8
9
  use Fleetbase\Http\Resources\FleetbaseResource;
9
10
  use Fleetbase\Support\Auth;
@@ -12,6 +13,18 @@ use Illuminate\Support\Str;
12
13
 
13
14
  class PaymentController extends Controller
14
15
  {
16
+ use AuthorizesMethods;
17
+
18
+ public function __construct()
19
+ {
20
+ $this->authorizeMethods([
21
+ 'hasStripeConnectAccount' => 'view payments',
22
+ 'getStripeAccount' => 'onboard payments',
23
+ 'getStripeAccountSession' => 'onboard payments',
24
+ 'getCompanyReceivedPayments' => 'view payments',
25
+ ]);
26
+ }
27
+
15
28
  /**
16
29
  * Checks if the currently authenticated company has an associated Stripe Connect account.
17
30
  *
@@ -19,6 +19,7 @@ use Fleetbase\FleetOps\Support\Radar\RadarAgenda;
19
19
  use Fleetbase\FleetOps\Support\Radar\RadarBriefing;
20
20
  use Fleetbase\FleetOps\Support\Radar\RadarItemState;
21
21
  use Fleetbase\FleetOps\Support\Radar\RadarRules;
22
+ use Fleetbase\FleetOps\Traits\AuthorizesMethods;
22
23
  use Fleetbase\Http\Controllers\Controller;
23
24
  use Fleetbase\Models\Alert;
24
25
  use Fleetbase\Models\CompanyUser;
@@ -42,6 +43,24 @@ use Illuminate\Support\Carbon;
42
43
  */
43
44
  class RadarController extends Controller
44
45
  {
46
+ use AuthorizesMethods;
47
+
48
+ public function __construct()
49
+ {
50
+ $this->authorizeMethods([
51
+ 'extendShift' => ['update driver', 'update vehicle'],
52
+ 'acknowledge' => ['update driver', 'update vehicle'],
53
+ 'snooze' => ['update driver', 'update vehicle'],
54
+ 'wake' => ['update driver', 'update vehicle'],
55
+ 'assign' => ['update driver', 'update vehicle'],
56
+ 'plan' => ['update driver', 'update vehicle'],
57
+ 'resolve' => ['update driver', 'update vehicle'],
58
+ 'bulk' => ['update driver', 'update vehicle'],
59
+ 'storeNotice' => ['update driver', 'update vehicle'],
60
+ 'destroyNotice' => ['update driver', 'update vehicle'],
61
+ ]);
62
+ }
63
+
45
64
  public const RESOLVED_WINDOW_DAYS = 7;
46
65
  public const SNOOZE_MAX_DAYS = 90;
47
66
 
@@ -7,6 +7,7 @@ use Fleetbase\FleetOps\Http\Controllers\FleetOpsController;
7
7
  use Fleetbase\FleetOps\Models\ServiceArea;
8
8
  use Fleetbase\Http\Requests\ExportRequest;
9
9
  use Illuminate\Http\Request;
10
+ use Illuminate\Support\Arr;
10
11
  use Illuminate\Support\Str;
11
12
  use Maatwebsite\Excel\Facades\Excel;
12
13
 
@@ -21,11 +22,16 @@ class ServiceAreaController extends FleetOpsController
21
22
 
22
23
  /**
23
24
  * Handle post save transactions.
25
+ *
26
+ * Reads the custom field values from the payload the base controller already extracted
27
+ * rather than from the raw request: Ember Data sends the resource under a camelCase root
28
+ * (`serviceArea`), so `$request->array('service_area.custom_field_values')` was always empty and no
29
+ * custom field value was ever persisted for this resource.
24
30
  */
25
- public function afterSave(Request $request, ServiceArea $serviceArea)
31
+ public function afterSave(Request $request, ServiceArea $serviceArea, array $input = [])
26
32
  {
27
- $customFieldValues = $request->array('service_area.custom_field_values');
28
- if ($customFieldValues) {
33
+ $customFieldValues = Arr::get($input, 'custom_field_values');
34
+ if (is_array($customFieldValues) && $customFieldValues) {
29
35
  $serviceArea->syncCustomFieldValues($customFieldValues);
30
36
  }
31
37
  }