Files
api/services/nginx/app/modules/edgegateway/routes/moduleEdgeGatewayRoute.php
T

431 lines
20 KiB
PHP

<?php
namespace routes;
use classes\authentication;
use classes\edge_gateway_manager;
use classes\edge_gateway_department_workspace_service;
use classes\edge_gateway_operation_exception;
use classes\edge_gateway_operation_service;
use classes\edge_gateway_registry_service;
use classes\edge_gateway_view_service;
use classes\edgegateway;
use classes\response;
use Exception;
use objects\logs_o;
use traits\route_t;
class moduleEdgeGatewayRoute
{
use route_t;
public function run(): void
{
$this->get('/modules/edge-gateways', fn() => $this->handleListGateways(), [
'modules_shelly_config' => 'List edge gateway module fleet',
]);
$this->get('/modules/edge-gateways/workspace/departments', fn() => $this->handleDepartmentWorkspaceList(), [
'modules_shelly_config' => 'List department hardware workspaces',
]);
$this->get('/modules/edge-gateways/workspace/departments/{id}', fn() => $this->handleDepartmentWorkspaceDetail(), [
'modules_shelly_config' => 'View department hardware workspace detail',
]);
$this->get('/modules/edge-gateways/{id}', fn() => $this->handleGatewayDetail(), [
'modules_shelly_config' => 'View edge gateway module detail',
]);
$this->get('/modules/edge-gateways/{id}/tasks', fn() => $this->handleGatewayTasksPage(), [
'modules_shelly_config' => 'View edge gateway module tasks',
]);
$this->get('/modules/edge-gateways/{id}/logs', fn() => $this->handleGatewayLogsPage(), [
'modules_shelly_config' => 'View edge gateway module logs',
]);
$this->get('/modules/edge-gateways/{id}/statistics', fn() => $this->handleGatewayStatisticsPage(), [
'modules_shelly_config' => 'View edge gateway module statistics',
]);
$this->post('/modules/edge-gateways/{id}/stream-session', fn() => $this->handleGatewayStreamSessionCreate(), [
'modules_shelly_config' => 'Create an edge gateway module live stream session',
]);
$this->put('/modules/edge-gateways/{id}', fn() => $this->handleGatewayUpdate(), [
'modules_shelly_config' => 'Update edge gateway module metadata',
]);
$this->get('/modules/edge-gateways/{id}/operations', fn() => $this->handleGatewayOperationsList(), [
'modules_shelly_config' => 'List edge gateway module operations',
]);
$this->post('/modules/edge-gateways/{id}/operations', fn() => $this->handleGatewayOperationCreate(), [
'modules_shelly_config' => 'Queue an edge gateway module operation',
]);
$this->post('/modules/edge-gateways/{id}/operations/{operationId}/cancel', fn() => $this->handleGatewayOperationCancel(), [
'modules_shelly_config' => 'Cancel an edge gateway module operation',
]);
$this->get('/modules/edge-gateways/{id}/operations/{operationId}/events', fn() => $this->handleGatewayOperationEvents(), [
'modules_shelly_config' => 'List edge gateway module operation events',
]);
$this->post('/modules/edge-gateways/{id}/rotate-credentials', fn() => $this->handleGatewayCredentialRotate(), [
'modules_shelly_config' => 'Rotate edge gateway module credentials',
]);
$this->post('/modules/edge-gateways/install-token', fn() => $this->handleInstallTokenCreate(), [
'modules_shelly_config' => 'Create an edge gateway module install token',
]);
$this->get('/modules/edge-gateways/install-token/{id}/status', fn() => $this->handleInstallTokenStatus(), [
'modules_shelly_config' => 'View edge gateway module installer status',
]);
$this->post('/modules/edge-gateways/{id}/discovery', fn() => $this->handleGatewayDiscovery(), [
'modules_shelly_config' => 'Queue discovery through the edge gateway module',
]);
$this->put('/modules/edge-gateways/{id}/bindings', fn() => $this->handleBindingsUpdate(), [
'modules_shelly_config' => 'Update edge gateway module relay bindings',
]);
$this->delete('/modules/edge-gateways/{id}', fn() => $this->handleGatewayDelete(), [
'modules_shelly_config' => 'Delete an edge gateway module registration',
]);
$this->post('/modules/edge-gateways/departments/{id}/cutover', fn() => $this->handleDepartmentCutover(), [
'modules_shelly_config' => 'Update department cutover through the edge gateway module',
]);
}
private function handleListGateways(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
$departmentId = self::isParametersSet(['department_id']) ? (int)self::getParameter('department_id') : null;
$view = trim((string)$this->fromQuery('view'));
if ($departmentId !== null && $departmentId > 0) {
$this->requireDepartmentAccess((string)$departmentId);
}
$payload = $this->views()->listGatewaysWithFleetUsage($departmentId, $view !== 'summary');
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_LIST', 'Listed edge gateways');
$response->add_meta('fleet_usage', $payload['fleet_usage']);
$response->success($payload['gateways']);
}
private function handleGatewayDetail(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
$gateway = $this->requireGatewayAccess((int)$this->fromRoute('id'));
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_GET', 'Fetched edge gateway detail');
$response->success($gateway);
}
private function handleDepartmentWorkspaceList(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
$summaries = $this->workspaces()->listDepartmentSummaries();
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_WORKSPACE_LIST', 'Listed department hardware workspace summaries');
$response->success($summaries);
}
private function handleDepartmentWorkspaceDetail(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
$departmentId = (int)$this->fromRoute('id');
self::requireParameterIntPositive($departmentId, 'id');
$this->requireDepartmentAccess((string)$departmentId);
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_WORKSPACE_GET', 'Fetched department hardware workspace detail');
$response->success($this->workspaces()->getDepartmentWorkspace($departmentId));
}
private function handleGatewayTasksPage(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
$gatewayId = (int)$this->fromRoute('id');
$this->requireGatewayAccess($gatewayId);
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_TASKS_GET', 'Fetched edge gateway task timeline');
$response->success($this->manager()->buildGatewayTasksPage($gatewayId));
}
private function handleGatewayLogsPage(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
$gatewayId = (int)$this->fromRoute('id');
$this->requireGatewayAccess($gatewayId);
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_LOGS_GET', 'Fetched edge gateway logs');
$response->success($this->manager()->buildGatewayLogsPage($gatewayId));
}
private function handleGatewayStatisticsPage(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
$gatewayId = (int)$this->fromRoute('id');
$this->requireGatewayAccess($gatewayId);
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_STATISTICS_GET', 'Fetched edge gateway statistics');
$response->success($this->manager()->buildGatewayStatisticsPage($gatewayId));
}
private function handleGatewayStreamSessionCreate(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
$gatewayId = (int)$this->fromRoute('id');
$this->requireGatewayAccess($gatewayId);
$payload = self::getParametersAsArray();
$scopes = isset($payload['scopes']) && is_array($payload['scopes']) ? (array)$payload['scopes'] : [];
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_STREAM_SESSION_CREATE', 'Created edge gateway stream session');
$response->success($this->manager()->createBrowserStreamSession($gatewayId, (int)$user->id, $scopes), 201);
}
private function handleGatewayUpdate(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
self::requireParameters(['label', 'is_primary']);
self::requireType(self::getParameter('label'), self::TYPE_STRING());
self::requireType(self::getParameter('is_primary'), self::TYPE_BOOL());
$gatewayId = (int)$this->fromRoute('id');
$this->requireGatewayAccess($gatewayId);
$result = $this->registry()->updateGatewayMetadata($gatewayId, [
'label' => (string)self::getParameter('label'),
'is_primary' => (bool)self::getParameter('is_primary'),
], (int)$user->id);
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_UPDATE', 'Updated edge gateway metadata');
$response->success($result);
}
private function handleGatewayOperationsList(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
$gatewayId = (int)$this->fromRoute('id');
$this->requireGatewayAccess($gatewayId);
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_OPERATIONS_LIST', 'Listed edge gateway operations');
$response->success($this->operations()->listOperations($gatewayId));
}
private function handleGatewayOperationCreate(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
self::requireParameters(['type', 'request']);
self::requireType(self::getParameter('type'), self::TYPE_STRING());
self::requireType(self::getParameter('request'), self::TYPE_ARRAY());
$gatewayId = (int)$this->fromRoute('id');
$this->requireGatewayAccess($gatewayId);
try {
$operation = $this->operations()->queueOperation(
$gatewayId,
(string)self::getParameter('type'),
(array)self::getParameter('request'),
(int)$user->id
);
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_OPERATION_QUEUE', 'Queued edge gateway operation');
$response->success([
'operation' => $operation,
'gateway' => $this->views()->getGateway($gatewayId),
], 201);
} catch (edge_gateway_operation_exception $exception) {
$response->error([
'message' => $exception->getMessage(),
'error_code' => $exception->errorCode,
], $exception->status);
}
}
private function handleGatewayOperationCancel(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
$gatewayId = (int)$this->fromRoute('id');
$operationId = (int)$this->fromRoute('operationId');
self::requireParameterIntPositive($operationId, 'operationId');
$this->requireGatewayAccess($gatewayId);
try {
$operation = $this->operations()->cancelOperation($gatewayId, $operationId, (int)$user->id);
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_OPERATION_CANCEL', 'Cancelled edge gateway operation');
$response->success([
'operation' => $operation,
'gateway' => $this->views()->getGateway($gatewayId),
]);
} catch (edge_gateway_operation_exception $exception) {
$response->error([
'message' => $exception->getMessage(),
'error_code' => $exception->errorCode,
], $exception->status);
}
}
private function handleGatewayOperationEvents(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
$gatewayId = (int)$this->fromRoute('id');
$operationId = (int)$this->fromRoute('operationId');
self::requireParameterIntPositive($operationId, 'operationId');
$this->requireGatewayAccess($gatewayId);
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_EVENTS_LIST', 'Listed edge gateway operation events');
$response->success($this->operations()->listOperationEvents($gatewayId, $operationId));
}
private function handleGatewayCredentialRotate(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
$gatewayId = (int)$this->fromRoute('id');
$this->requireGatewayAccess($gatewayId);
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_CREDENTIALS_ROTATE', 'Rotated edge gateway credentials');
$response->success($this->operations()->rotateCredentials($gatewayId, (int)$user->id));
}
private function handleInstallTokenCreate(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
self::requireParameters(['department_id']);
$departmentId = (int)self::getParameter('department_id');
self::requireParameterIntPositive($departmentId, 'department_id');
$this->requireDepartmentAccess((string)$departmentId);
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_INSTALL_TOKEN_CREATE', 'Created edge gateway install token');
$response->success(
$this->registry()->createInstallToken(
$departmentId,
self::isParametersSet(['label']) ? (string)self::getParameter('label') : null,
(int)$user->id
),
201
);
}
private function handleInstallTokenStatus(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
$claimTokenId = (int)$this->fromRoute('id');
self::requireParameterIntPositive($claimTokenId, 'id');
$status = $this->registry()->getInstallTokenStatus($claimTokenId);
$departmentId = (int)($status['department_id'] ?? 0);
self::requireParameterIntPositive($departmentId, 'department_id');
$this->requireDepartmentAccess((string)$departmentId);
(new logs_o())->add(
'modules_edgegateway',
'global',
1,
$user->id,
'MODULES_EDGEGATEWAY_INSTALL_TOKEN_STATUS',
'Viewed edge gateway installer status'
);
unset($status['department_id']);
$response->success($status);
}
private function handleGatewayDiscovery(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
$gatewayId = (int)$this->fromRoute('id');
$this->requireGatewayAccess($gatewayId);
$this->operations()->queueDiscoveryOperation($gatewayId, (int)$user->id);
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_DISCOVERY_QUEUE', 'Queued edge gateway discovery');
$response->success($this->views()->getGateway($gatewayId));
}
private function handleBindingsUpdate(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
self::requireParameters(['bindings']);
self::requireType(self::getParameter('bindings'), self::TYPE_ARRAY());
$gatewayId = (int)$this->fromRoute('id');
$this->requireGatewayAccess($gatewayId);
$this->registry()->setRelayBindings($gatewayId, (array)self::getParameter('bindings'), (int)$user->id);
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_BINDINGS_UPDATE', 'Updated edge gateway bindings');
$response->success($this->views()->getGateway($gatewayId));
}
private function handleGatewayDelete(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
$gatewayId = (int)$this->fromRoute('id');
$this->requireGatewayAccess($gatewayId);
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_DELETE', 'Deleted edge gateway');
$response->success($this->registry()->deleteGateway($gatewayId, (int)$user->id));
}
private function handleDepartmentCutover(): void
{
global /** @var response $response */ $response;
$user = $this->requireModuleOperator();
self::requireParameters(['transport_mode']);
$departmentId = (int)$this->fromRoute('id');
self::requireParameterIntPositive($departmentId, 'id');
$this->requireDepartmentAccess((string)$departmentId);
(new logs_o())->add('modules_edgegateway', 'global', 1, $user->id, 'MODULES_EDGEGATEWAY_DEPARTMENT_CUTOVER', 'Updated department gateway cutover');
$response->success($this->registry()->setDepartmentTransportMode($departmentId, (string)self::getParameter('transport_mode'), (int)$user->id));
}
private function requireModuleOperator(): object
{
global /** @var response $response */ $response;
$this->requirePermission('modules_shelly_config');
try {
(new edgegateway())->requireModuleEnabled();
} catch (Exception $exception) {
$response->error($exception->getMessage(), 409);
}
$user = (new authentication())->get_user();
if (!$user) {
$response->error('Invalid session', 400);
}
return $user;
}
private function requireGatewayAccess(int $gatewayId): array
{
global /** @var response $response */ $response;
$gateway = $this->views()->getGateway($gatewayId);
if (!isset($gateway['id'])) {
$response->error('Edge gateway not found', 404);
}
$departmentId = (int)($gateway['department_id'] ?? 0);
self::requireParameterIntPositive($departmentId, 'department_id');
$this->requireDepartmentAccess((string)$departmentId);
return $gateway;
}
private function views(): edge_gateway_view_service
{
return new edge_gateway_view_service();
}
private function registry(): edge_gateway_registry_service
{
return new edge_gateway_registry_service();
}
private function operations(): edge_gateway_operation_service
{
return new edge_gateway_operation_service();
}
private function manager(): edge_gateway_manager
{
return new edge_gateway_manager();
}
private function workspaces(): edge_gateway_department_workspace_service
{
return new edge_gateway_department_workspace_service();
}
}