- Introduce `requestBooleanFlag` method for consistent boolean parameter handling with default values. - Add `activate_machine` and `sync_relay_state` parameters to `synchronizeSession` for more flexible relay and machine activation control. - Update methods, routes, and tests to integrate the new session synchronization parameters effectively. - Enhance debugging support with additional metadata in simulation and payload captures.
226 lines
11 KiB
PHP
226 lines
11 KiB
PHP
<?php
|
|
|
|
namespace routes;
|
|
|
|
use classes\authentication;
|
|
use modules\selfserve\classes\selfserve_config_versioning;
|
|
use modules\selfserve\classes\selfserve_studio_graph;
|
|
use modules\selfserve\classes\selfserve_wash_flow;
|
|
use objects\logs_o;
|
|
use traits\route_t;
|
|
|
|
class departmentSelfserveStudioRoute
|
|
{
|
|
use route_t;
|
|
|
|
public function run(): void
|
|
{
|
|
$this->get('/department/selfserve/studio/graph', function (): void {
|
|
global $response;
|
|
$user = $this->requireStudioUser('list_department_selfserve_config_versions');
|
|
self::requireParameters(['department']);
|
|
$departmentId = (int)self::getParameter('department');
|
|
$this->assertDepartmentAccess($user, $departmentId, ['view_all_department_selfserve_config_versions']);
|
|
|
|
$service = new selfserve_studio_graph();
|
|
(new logs_o())->add('selfserve_studio', $departmentId, 1, $user->id, 'GET_STUDIO_GRAPH', 'Fetched self-serve studio graph');
|
|
$response->success($service->buildGraph($departmentId, (int)$user->id, $this->studioPermissions()));
|
|
}, [
|
|
'list_department_selfserve_config_versions' => 'View the all-in-one self-serve studio graph',
|
|
'view_all_department_selfserve_config_versions' => 'View the all-in-one self-serve studio graph across departments',
|
|
]);
|
|
|
|
$this->put('/department/selfserve/studio/graph', function (): void {
|
|
global $response;
|
|
$user = $this->requireStudioUser('edit_department_selfserve_config_versions');
|
|
self::requireParameters(['department']);
|
|
$departmentId = (int)self::getParameter('department');
|
|
$this->assertDepartmentAccess($user, $departmentId);
|
|
|
|
try {
|
|
$payload = self::getParametersAsArray();
|
|
$service = new selfserve_studio_graph();
|
|
$graph = $service->applyGraphSave($departmentId, $payload, (int)$user->id, $this->studioPermissions());
|
|
(new logs_o())->add('selfserve_studio', $departmentId, 1, $user->id, 'SAVE_STUDIO_GRAPH', 'Saved self-serve studio graph');
|
|
$response->success($graph);
|
|
} catch (\RuntimeException $exception) {
|
|
$response->error($exception->getMessage(), 422);
|
|
}
|
|
}, [
|
|
'edit_department_selfserve_config_versions' => 'Create, update, delete, connect, and reorder self-serve studio graph objects',
|
|
]);
|
|
|
|
$this->put('/department/selfserve/studio/layout', function (): void {
|
|
global $response;
|
|
$user = $this->requireStudioUser('edit_department_selfserve_config_versions');
|
|
self::requireParameters(['department', 'layout']);
|
|
self::requireType(self::getParameter('layout'), self::TYPE_ARRAY());
|
|
$departmentId = (int)self::getParameter('department');
|
|
$this->assertDepartmentAccess($user, $departmentId);
|
|
|
|
try {
|
|
$layout = (new selfserve_studio_graph())->saveLayout($departmentId, (int)$user->id, (array)self::getParameter('layout'));
|
|
(new logs_o())->add('selfserve_studio', $departmentId, 1, $user->id, 'SAVE_STUDIO_LAYOUT', 'Saved self-serve studio layout');
|
|
$response->success($layout);
|
|
} catch (\RuntimeException $exception) {
|
|
$response->error($exception->getMessage(), 422);
|
|
}
|
|
}, [
|
|
'edit_department_selfserve_config_versions' => 'Save canvas-only self-serve studio layout',
|
|
]);
|
|
|
|
$this->post('/department/selfserve/studio/validate', function (): void {
|
|
global $response;
|
|
$user = $this->requireStudioUser('edit_department_selfserve_config_versions');
|
|
self::requireParameters(['department']);
|
|
$departmentId = (int)self::getParameter('department');
|
|
$this->assertDepartmentAccess($user, $departmentId);
|
|
|
|
$validation = (new selfserve_studio_graph())->validatePayload($departmentId, self::getParametersAsArray());
|
|
(new logs_o())->add('selfserve_studio', $departmentId, 1, $user->id, 'VALIDATE_STUDIO_GRAPH', 'Validated self-serve studio graph');
|
|
$response->success($validation);
|
|
}, [
|
|
'edit_department_selfserve_config_versions' => 'Validate the self-serve studio graph',
|
|
]);
|
|
|
|
$this->post('/department/selfserve/studio/simulate', function (): void {
|
|
global $response;
|
|
$user = $this->requireStudioUser('list_department_selfserve_vehicle_conditions');
|
|
self::requireParameters(['department', 'lane_id', 'reg']);
|
|
$departmentId = (int)self::getParameter('department');
|
|
$laneId = (int)self::getParameter('lane_id');
|
|
self::requireParameterIntPositive($laneId, 'lane_id');
|
|
$this->assertDepartmentAccess($user, $departmentId);
|
|
|
|
try {
|
|
$result = (new selfserve_studio_graph())->simulateGraph(
|
|
$departmentId,
|
|
self::getParametersAsArray(),
|
|
(int)$user->id,
|
|
$this->studioPermissions()
|
|
);
|
|
(new logs_o())->add('selfserve_studio', $departmentId, 1, $user->id, 'SIMULATE_STUDIO_GRAPH', 'Simulated self-serve studio graph');
|
|
$response->success($result);
|
|
} catch (\Throwable $exception) {
|
|
$response->error($exception->getMessage(), 422);
|
|
}
|
|
}, [
|
|
'list_department_selfserve_vehicle_conditions' => 'Run the self-serve studio simulator',
|
|
]);
|
|
|
|
$this->post('/department/selfserve/studio/publish', function (): void {
|
|
global $response;
|
|
$user = $this->requireStudioUser('publish_department_selfserve_config_versions');
|
|
self::requireParameters(['department']);
|
|
$departmentId = (int)self::getParameter('department');
|
|
$this->assertDepartmentAccess($user, $departmentId);
|
|
|
|
try {
|
|
$published = (new selfserve_config_versioning())->publishDraft($departmentId, (int)$user->id);
|
|
(new logs_o())->add('selfserve_studio', $departmentId, 1, $user->id, 'PUBLISH_STUDIO_GRAPH', 'Published self-serve studio graph');
|
|
$response->success($published);
|
|
} catch (\RuntimeException $exception) {
|
|
$response->error($exception->getMessage(), 422);
|
|
}
|
|
}, [
|
|
'publish_department_selfserve_config_versions' => 'Publish the self-serve studio draft',
|
|
]);
|
|
|
|
$this->post('/department/selfserve/studio/rollback', function (): void {
|
|
global $response;
|
|
$user = $this->requireStudioUser('rollback_department_selfserve_config_versions');
|
|
self::requireParameters(['department', 'target_version_id']);
|
|
$departmentId = (int)self::getParameter('department');
|
|
$targetVersionId = (int)self::getParameter('target_version_id');
|
|
self::requireParameterIntPositive($targetVersionId, 'target_version_id');
|
|
$this->assertDepartmentAccess($user, $departmentId);
|
|
|
|
try {
|
|
$rolledBack = (new selfserve_config_versioning())->rollbackToVersion($departmentId, $targetVersionId, (int)$user->id);
|
|
(new logs_o())->add('selfserve_studio', $departmentId, 1, $user->id, 'ROLLBACK_STUDIO_GRAPH', 'Rolled back self-serve studio graph');
|
|
$response->success($rolledBack);
|
|
} catch (\RuntimeException $exception) {
|
|
$response->error($exception->getMessage(), 422);
|
|
}
|
|
}, [
|
|
'rollback_department_selfserve_config_versions' => 'Rollback the self-serve studio draft to an earlier version',
|
|
]);
|
|
|
|
$this->post('/department/selfserve/studio/gateway-action', function (): void {
|
|
global $response;
|
|
$user = $this->requireStudioUser('modules_shelly_config');
|
|
self::requireParameters(['department', 'gateway_id', 'action']);
|
|
$departmentId = (int)self::getParameter('department');
|
|
$gatewayId = (int)self::getParameter('gateway_id');
|
|
self::requireParameterIntPositive($gatewayId, 'gateway_id');
|
|
$this->assertDepartmentAccess($user, $departmentId);
|
|
|
|
$action = strtolower((string)self::getParameter('action'));
|
|
$confirmed = filter_var(self::getParameter('confirm'), FILTER_VALIDATE_BOOLEAN);
|
|
if (in_array($action, ['uninstall', 'rotate_credentials'], true) && $confirmed !== true) {
|
|
$response->error('This gateway action requires explicit confirmation.', 428);
|
|
}
|
|
|
|
try {
|
|
$payload = self::getParametersAsArray();
|
|
$result = (new selfserve_studio_graph())->runGatewayAction($departmentId, $gatewayId, $action, $payload, (int)$user->id);
|
|
(new logs_o())->add('selfserve_studio', $departmentId, 1, $user->id, 'GATEWAY_STUDIO_ACTION', 'Ran self-serve studio gateway action: ' . $action);
|
|
$response->success($result);
|
|
} catch (\Throwable $exception) {
|
|
$response->error($exception->getMessage(), 422);
|
|
}
|
|
}, [
|
|
'modules_shelly_config' => 'Run permission-gated self-serve studio edge gateway actions',
|
|
]);
|
|
}
|
|
|
|
private function requireStudioUser(string $permission): object
|
|
{
|
|
global $response;
|
|
$this->requirePermission($permission);
|
|
$user = (new authentication())->get_user();
|
|
if (!$user) {
|
|
$response->error('Invalid session', 400);
|
|
}
|
|
|
|
return $user;
|
|
}
|
|
|
|
/**
|
|
* @param array<int,string> $bypassPermissions
|
|
*/
|
|
private function assertDepartmentAccess(object $user, int $departmentId, array $bypassPermissions = []): void
|
|
{
|
|
$authorizedDepartmentIds = $user->getGroup()->getDepartments();
|
|
if (in_array($departmentId, $authorizedDepartmentIds, true)) {
|
|
return;
|
|
}
|
|
|
|
foreach ($bypassPermissions as $permission) {
|
|
if ($this->hasPermission($permission)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
$this->forbidDepartmentAccess($departmentId, $bypassPermissions);
|
|
}
|
|
|
|
/**
|
|
* @return array<string,bool>
|
|
*/
|
|
private function studioPermissions(): array
|
|
{
|
|
return [
|
|
'can_view' => $this->hasPermission('list_department_selfserve_config_versions'),
|
|
'can_edit' => $this->hasPermission('edit_department_selfserve_config_versions'),
|
|
'can_publish' => $this->hasPermission('publish_department_selfserve_config_versions'),
|
|
'can_rollback' => $this->hasPermission('rollback_department_selfserve_config_versions'),
|
|
'can_simulate' => $this->hasPermission('list_department_selfserve_vehicle_conditions'),
|
|
'modules_shelly_config' => $this->hasPermission('modules_shelly_config'),
|
|
'can_manage_gateways' => $this->hasPermission('modules_shelly_config'),
|
|
'can_run_gateway_destructive_actions' => $this->hasPermission('modules_shelly_config'),
|
|
'can_run_live_lane_actions' => $this->hasPermission('modules_selfserve_sessions_force_stop'),
|
|
];
|
|
}
|
|
}
|