@velor/remote-mouse 6.4.8
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.
- package/.artifacts/screenshots/remote-mobile-config.png +0 -0
- package/.artifacts/screenshots/remote-mobile-home.png +0 -0
- package/.artifacts/screenshots/remote-mobile-preferences.png +0 -0
- package/.artifacts/screenshots/remote-mobile-server-info.png +0 -0
- package/.artifacts/screenshots/remote-mobile-vlc.png +0 -0
- package/.env.example +93 -0
- package/README.md +370 -0
- package/bin/remote-mouse.js +19 -0
- package/client/core/dom.js +148 -0
- package/client/core/init-socket-io.js +117 -0
- package/client/core/socket-emit.js +6 -0
- package/client/core/window-events.js +23 -0
- package/client/i18n/apply-page-translations.js +18 -0
- package/client/i18n/constants.js +3 -0
- package/client/i18n/core.js +40 -0
- package/client/i18n/locale-registry.js +77 -0
- package/client/i18n/locales/de.js +227 -0
- package/client/i18n/locales/en.js +389 -0
- package/client/i18n/locales/es.js +228 -0
- package/client/i18n/locales/fr.js +389 -0
- package/client/i18n/locales/it.js +227 -0
- package/client/i18n/locales/ja.js +227 -0
- package/client/i18n/locales/pt.js +227 -0
- package/client/i18n/locales/ru.js +240 -0
- package/client/i18n/locales/zh.js +227 -0
- package/client/preferences/constants.js +15 -0
- package/client/preferences/effects.js +24 -0
- package/client/preferences/load.js +19 -0
- package/client/preferences/render.js +26 -0
- package/client/preferences/rows.js +78 -0
- package/client/preferences/state.js +29 -0
- package/client/preview/create-preview-frame-receiver.js +13 -0
- package/client/preview/draw.js +77 -0
- package/client/preview/parse-preview-frame.js +39 -0
- package/client/preview/preview-stream.js +152 -0
- package/client/services/app-state/appStateKeys.js +30 -0
- package/client/services/app-state/createAppStateService.js +216 -0
- package/client/services/app-state/createPersistStoreService.js +122 -0
- package/client/services/app-state/createStateStoreService.js +64 -0
- package/client/services/app-state/localStorageBinding.js +26 -0
- package/client/services/app-state/normalizers.js +74 -0
- package/client/services/app-state/resolveEffectiveStateValue.js +58 -0
- package/client/services/app-state/stateDefinitions.js +107 -0
- package/client/services/backend/createBackendService.js +55 -0
- package/client/services/config/ConfigView.js +45 -0
- package/client/services/config/createClientConfigService.js +122 -0
- package/client/services/config/defaultClientConfig.js +22 -0
- package/client/services/createServicesContainer.js +48 -0
- package/client/services/createServicesRegistry.js +26 -0
- package/client/services/i18n/createI18nService.js +86 -0
- package/client/services/notifications/createNotificationService.js +56 -0
- package/client/services/pubsub/createPubSubService.js +20 -0
- package/client/services/remotes/createRemotesService.js +20 -0
- package/client/services/transport/createSocketIoTransportService.js +50 -0
- package/client/touch/bindTouchPassthrough.js +94 -0
- package/client/touch/createTouchList.js +18 -0
- package/client/touch/dispatchSyntheticTouch.js +20 -0
- package/client/touch/gesture-zone.js +28 -0
- package/client/touch/throttle.js +46 -0
- package/client/touch/touch-handlers.js +193 -0
- package/client/touch/touchpad.js +231 -0
- package/client/ui/config/page.js +840 -0
- package/client/ui/main/applyRemoteVisibilityState.js +60 -0
- package/client/ui/main/bind-client-notifications.js +3 -0
- package/client/ui/main/bindings/bindAccordion.js +121 -0
- package/client/ui/main/bindings/bindActionButtons.js +13 -0
- package/client/ui/main/bindings/bindAdminDrawer.js +137 -0
- package/client/ui/main/bindings/bindAdminRemoteButtons.js +77 -0
- package/client/ui/main/bindings/bindAdminVersion.js +27 -0
- package/client/ui/main/bindings/bindBrowserRemoteButtons.js +119 -0
- package/client/ui/main/bindings/bindRemoteAccordion.js +23 -0
- package/client/ui/main/bindings/bindSamsungRemoteButtons.js +320 -0
- package/client/ui/main/bindings/bindSystemRemoteButtons.js +41 -0
- package/client/ui/main/bindings/bindVlcRemoteButtons.js +64 -0
- package/client/ui/main/canvas-ui.js +33 -0
- package/client/ui/main/connection-overlay.js +57 -0
- package/client/ui/main/init-ui.js +54 -0
- package/client/ui/main/keyboard-panel.js +271 -0
- package/client/ui/main/mouse-buttons.js +94 -0
- package/client/ui/main/page.js +21 -0
- package/client/ui/notifications/show-toast.js +48 -0
- package/client/ui/preferences/bindPreferenceSwitchers.js +49 -0
- package/client/ui/preferences/page.js +61 -0
- package/client/ui/preferences/switchers.js +200 -0
- package/index.js +9 -0
- package/package.json +41 -0
- package/public/admin-config.css +447 -0
- package/public/admin-config.html +63 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/brave-icon.svg +13 -0
- package/public/favicon.svg +30 -0
- package/public/icon-192.png +0 -0
- package/public/icon-512.png +0 -0
- package/public/index.html +246 -0
- package/public/manifest.webmanifest +45 -0
- package/public/preferences.html +55 -0
- package/public/server-info.html +574 -0
- package/public/styles.css +1042 -0
- package/public/sw.js +103 -0
- package/scripts/codex-commit.sh +112 -0
- package/scripts/generate-mobile-screenshots.mjs +244 -0
- package/scripts/install-linux.sh +633 -0
- package/scripts/install-windows.ps1 +369 -0
- package/server/application/createApplicationLifecycle.js +15 -0
- package/server/application/logger.js +216 -0
- package/server/application/shutdown.js +81 -0
- package/server/application/start.js +95 -0
- package/server/application/state.js +19 -0
- package/server/connection/api/admin-actions.router.js +65 -0
- package/server/connection/api/admin-configs.router.js +165 -0
- package/server/connection/api/admin-remotes.router.js +61 -0
- package/server/connection/api/admin-subs.router.js +49 -0
- package/server/connection/api/client.router.js +15 -0
- package/server/connection/api/configs.js +96 -0
- package/server/connection/api/qr-page.handler.js +17 -0
- package/server/connection/api/remotes.router.js +30 -0
- package/server/connection/api/server-info.router.js +149 -0
- package/server/connection/api/session.middleware.js +93 -0
- package/server/connection/api/unauthorized-response.js +73 -0
- package/server/connection/socket/createConnectionRegistrar.js +23 -0
- package/server/connection/socket/createSocketSessionAuthMiddleware.js +49 -0
- package/server/connection/socket/socket-action-responder.js +12 -0
- package/server/connection/socket/socket.timestamp-middleware.js +51 -0
- package/server/index.js +12 -0
- package/server/init/bootstrapApi.js +87 -0
- package/server/init/bootstrapSocket.js +79 -0
- package/server/init/createAdminApiRouter.js +22 -0
- package/server/init/createAdminUiRouter.js +21 -0
- package/server/init/createSocketActionRegistrars.js +52 -0
- package/server/init/observers/startConfigObserver.js +51 -0
- package/server/init/observers/startDisplaySizeObserver.js +55 -0
- package/server/init/observers/startNotificationObserver.js +49 -0
- package/server/init/observers/startQrOverlayHoverObserver.js +89 -0
- package/server/init/observers/startQrOverlayRefreshObserver.js +53 -0
- package/server/os/darwin/app.js +45 -0
- package/server/os/darwin/applescript.js +51 -0
- package/server/os/darwin/cliSocket.js +53 -0
- package/server/os/darwin/url.js +9 -0
- package/server/os/darwin/window.js +10 -0
- package/server/os/linux/app.js +120 -0
- package/server/os/linux/cliSocket.js +53 -0
- package/server/os/linux/process.js +69 -0
- package/server/os/linux/screen.js +58 -0
- package/server/os/linux/systemd.js +139 -0
- package/server/os/linux/url.js +17 -0
- package/server/os/linux/windows.js +144 -0
- package/server/os/win32/app.js +66 -0
- package/server/os/win32/cliSocket.js +15 -0
- package/server/os/win32/powershell.js +70 -0
- package/server/os/win32/process.js +20 -0
- package/server/os/win32/service.js +95 -0
- package/server/os/win32/url.js +9 -0
- package/server/os/win32/window.js +10 -0
- package/server/remotes/admin/createAdminEventGuardMiddleware.js +29 -0
- package/server/remotes/admin/createForceUpdateCheckAction.js +39 -0
- package/server/remotes/admin/createInstallUpdateAction.js +64 -0
- package/server/remotes/admin/createOpenQrBrowserAction.js +63 -0
- package/server/remotes/admin/createOpenServerInfoBrowserAction.js +58 -0
- package/server/remotes/admin/createRestartServiceAction.js +20 -0
- package/server/remotes/admin/createRotateEntryTokenAction.js +43 -0
- package/server/remotes/admin/createToggleQrOverlayAction.js +38 -0
- package/server/remotes/admin/index.js +32 -0
- package/server/remotes/admin/notifyIfRestarted.js +102 -0
- package/server/remotes/admin/registrar.js +94 -0
- package/server/remotes/browser/actions/createFocusOrLaunchBrowserAction.js +22 -0
- package/server/remotes/browser/actions/openUrlOnHost.js +3 -0
- package/server/remotes/browser/browserCatalog.js +70 -0
- package/server/remotes/browser/index.js +15 -0
- package/server/remotes/browser/listBrowsersOnHost.js +23 -0
- package/server/remotes/browser/registrar.js +29 -0
- package/server/remotes/browser/spec.js +18 -0
- package/server/remotes/browser/state.js +5 -0
- package/server/remotes/input/registrar.js +39 -0
- package/server/remotes/preview/bgraToRgbaBuffer.js +20 -0
- package/server/remotes/preview/captureAroundCursor.js +19 -0
- package/server/remotes/preview/createPreviewStreamer.js +85 -0
- package/server/remotes/preview/registrar.js +34 -0
- package/server/remotes/samsung/createSamsungCommandService.js +203 -0
- package/server/remotes/samsung/createSamsungRemote.js +26 -0
- package/server/remotes/samsung/createSamsungRemoteGetter.js +46 -0
- package/server/remotes/samsung/createSamsungTvGetter.js +102 -0
- package/server/remotes/samsung/device-config.js +122 -0
- package/server/remotes/samsung/registrar.js +59 -0
- package/server/remotes/samsung/utils.js +56 -0
- package/server/remotes/vlc/index.js +39 -0
- package/server/remotes/vlc/registrar.js +94 -0
- package/server/remotes/vlc/spec.js +15 -0
- package/server/remotes/vlc/state.js +5 -0
- package/server/remotes/window/index.js +6 -0
- package/server/remotes/window/registrar.js +28 -0
- package/server/services/application/createApplicationDaemonService.js +144 -0
- package/server/services/application/getDaemonServiceAdapter.js +56 -0
- package/server/services/application/utils.js +29 -0
- package/server/services/config/bootstrapConfig.js +38 -0
- package/server/services/config/configPaths.js +42 -0
- package/server/services/config/configSchema.js +297 -0
- package/server/services/config/configService.js +89 -0
- package/server/services/config/defaultConfig.js +137 -0
- package/server/services/config/envConfig.js +49 -0
- package/server/services/config/index.js +9 -0
- package/server/services/config/logConfig.js +54 -0
- package/server/services/config/system-config.js +44 -0
- package/server/services/createServicesContainer.js +94 -0
- package/server/services/createServicesRegistry.js +48 -0
- package/server/services/input/createInputController.js +17 -0
- package/server/services/input/createKeyboardController.js +146 -0
- package/server/services/input/createMouseController.js +182 -0
- package/server/services/notifier/createClientNotifier.js +23 -0
- package/server/services/notifier/createHostNotifier.js +41 -0
- package/server/services/notifier/createNotifier.js +13 -0
- package/server/services/notifier/createNotifierComposite.js +122 -0
- package/server/services/notifier/handleOpenQrBrowserEvent.js +40 -0
- package/server/services/notifier/handleOpenServerInfoBrowserEvent.js +40 -0
- package/server/services/notifier/handleRestartServiceEvent.js +37 -0
- package/server/services/notifier/handleRotateEntryTokenEvent.js +42 -0
- package/server/services/notifier/handleSessionEvent.js +24 -0
- package/server/services/notifier/handleToggleQrOverlayEvent.js +21 -0
- package/server/services/notifier/host-notifier/createLinuxHostNotifier.js +23 -0
- package/server/services/notifier/host-notifier/createNodeNotifierHostNotifier.js +24 -0
- package/server/services/notifier/host-notifier/index.js +11 -0
- package/server/services/notifier/mapper/handleForceUpdateCheckEvent.js +24 -0
- package/server/services/notifier/mapper/handleInstallUpdateEvent.js +53 -0
- package/server/services/notifier/mapper/handleSocketEvent.js +40 -0
- package/server/services/notifier/mapper/handleUpdateManagerEvent.js +24 -0
- package/server/services/notifier/mapper/notify.js +7 -0
- package/server/services/os/index.js +23 -0
- package/server/services/os/platforms/createFallbackAdapter.js +31 -0
- package/server/services/os/platforms/darwin/app.js +6 -0
- package/server/services/os/platforms/darwin/index.js +21 -0
- package/server/services/os/platforms/darwin/scripts.js +4 -0
- package/server/services/os/platforms/darwin/url.js +1 -0
- package/server/services/os/platforms/darwin/window.js +4 -0
- package/server/services/os/platforms/linux/app.js +6 -0
- package/server/services/os/platforms/linux/index.js +33 -0
- package/server/services/os/platforms/linux/url.js +1 -0
- package/server/services/os/platforms/linux/windows.js +11 -0
- package/server/services/os/platforms/win32/app.js +6 -0
- package/server/services/os/platforms/win32/index.js +21 -0
- package/server/services/os/platforms/win32/overlay.js +6 -0
- package/server/services/os/platforms/win32/powershell.js +4 -0
- package/server/services/os/platforms/win32/url.js +1 -0
- package/server/services/os/platforms/win32/window.js +4 -0
- package/server/services/os/shared.js +2 -0
- package/server/services/overlay/createNoopOverlay.js +13 -0
- package/server/services/overlay/createQrOverlay.js +27 -0
- package/server/services/overlay/createQrOverlayWin32.js +158 -0
- package/server/services/overlay/createQrOverlayYad.js +178 -0
- package/server/services/overlay/renderQrPage.js +82 -0
- package/server/services/persistence/createConfigDao.js +106 -0
- package/server/services/persistence/createDatabaseProvider.js +23 -0
- package/server/services/persistence/createEntryTokenDao.js +140 -0
- package/server/services/persistence/createRestartLogDao.js +210 -0
- package/server/services/persistence/index.js +19 -0
- package/server/services/pubsub/createEventStore.js +54 -0
- package/server/services/pubsub/createPubSub.js +89 -0
- package/server/services/pubsub/createServiceEvents.js +29 -0
- package/server/services/pubsub/serviceEventConstants.js +39 -0
- package/server/services/remotes/createRemotes.js +25 -0
- package/server/services/server/createHttpsServer.js +12 -0
- package/server/services/server/createServer.js +66 -0
- package/server/services/sse/createSseService.js +96 -0
- package/server/services/sse/utils.js +7 -0
- package/server/services/system/createSystemService.js +170 -0
- package/server/services/system/getNetworkInfo.js +18 -0
- package/server/services/system/getScreenInfo.js +32 -0
- package/server/services/system/listNetworkInterfaces.js +27 -0
- package/server/services/task-manager/createTaskManager.js +68 -0
- package/server/services/task-runner/createTaskRunner.js +114 -0
- package/server/services/token-manager/createTokenManager.js +244 -0
- package/server/services/token-manager/token-format.js +7 -0
- package/server/services/token-manager/token-store-utils.js +8 -0
- package/server/services/update-manager/CommandUpdateSource.js +70 -0
- package/server/services/update-manager/NpmUpdateSource.js +34 -0
- package/server/services/update-manager/buildNpmGlobalUpdateCommand.js +15 -0
- package/server/services/update-manager/chooseUpdateCheckSource.js +20 -0
- package/server/services/update-manager/chooseUpdateInstallSource.js +5 -0
- package/server/services/update-manager/createUpdateManager.js +109 -0
- package/server/services/update-manager/resolveInstallUpdateCommand.js +42 -0
- package/server/term/cli/executeLocalServiceCommand.js +42 -0
- package/server/term/cli/getCliSocketPath.js +5 -0
- package/server/term/cli/parseCliArgs.js +110 -0
- package/server/term/cli/printCliResult.js +18 -0
- package/server/term/cli/runCliCmd.js +50 -0
- package/server/term/cli/sendCliCommand.js +76 -0
- package/server/term/cliSocket.js +29 -0
- package/server/term/srv/commands/configCommand.js +84 -0
- package/server/term/srv/commands/helpCommand.js +6 -0
- package/server/term/srv/commands/infoCommand.js +7 -0
- package/server/term/srv/commands/openQrCommand.js +7 -0
- package/server/term/srv/commands/samsungDetectCommand.js +52 -0
- package/server/term/srv/commands/serviceCommand.js +25 -0
- package/server/term/srv/commands/systemConfigCommand.js +7 -0
- package/server/term/srv/commands/tasksCommand.js +24 -0
- package/server/term/srv/commands/tokensCommand.js +15 -0
- package/server/term/srv/executeCliCommand.js +44 -0
- package/server/term/srv/executeCliRequest.js +38 -0
- package/server/term/srv/startCliServer.js +140 -0
- package/server/utils/createRandomToken.js +11 -0
- package/server/utils/env.js +155 -0
- package/server/utils/git.js +13 -0
- package/server/utils/http.js +7 -0
- package/server/utils/network.js +45 -0
- package/server/utils/paths.js +10 -0
- package/server/utils/process.js +57 -0
- package/server/utils/robot.js +11 -0
- package/server/utils/semver.js +33 -0
- package/server/utils/truncateText.js +7 -0
- package/utils/createLazy.js +13 -0
- package/utils/functional.js +48 -0
- package/utils/math.js +26 -0
- package/utils/notificationSettings.js +61 -0
- package/utils/object.utils.js +79 -0
- package/utils/predicates.js +17 -0
- package/utils/remoteCommands.js +40 -0
- package/utils/sync.js +3 -0
- package/velor-remote-mouse-6.4.8.tgz +0 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import {createHash} from 'node:crypto';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import {computeTokenTtlMs} from '../../services/token-manager/token-store-utils.js';
|
|
5
|
+
import {publicDir, projectRoot} from '../../utils/paths.js';
|
|
6
|
+
import {getRecentLogs} from '../../application/logger.js';
|
|
7
|
+
import {readPackageVersion} from '../../utils/env.js';
|
|
8
|
+
|
|
9
|
+
const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
10
|
+
|
|
11
|
+
function redactSecrets(value, key = '') {
|
|
12
|
+
const keyLower = String(key || '').toLowerCase();
|
|
13
|
+
if (keyLower.includes('secret') || keyLower.includes('password')) {
|
|
14
|
+
return '[redacted]';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (Array.isArray(value)) {
|
|
18
|
+
return value.map((item) => redactSecrets(item));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (value && typeof value === 'object') {
|
|
22
|
+
const out = {};
|
|
23
|
+
for (const [childKey, childValue] of Object.entries(value)) {
|
|
24
|
+
out[childKey] = redactSecrets(childValue, childKey);
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getConnectedClients(io) {
|
|
33
|
+
return Array.from(io.of('/').sockets.values()).map((socket) => ({
|
|
34
|
+
id: socket.id,
|
|
35
|
+
connectedAt: Number.isFinite(socket?.handshake?.issued)
|
|
36
|
+
? new Date(socket.handshake.issued).toISOString()
|
|
37
|
+
: null,
|
|
38
|
+
address: socket?.handshake?.address || socket?.conn?.remoteAddress || null,
|
|
39
|
+
transport: socket?.conn?.transport?.name || 'unknown',
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function maskToken(token) {
|
|
44
|
+
const normalized = String(token || '').trim();
|
|
45
|
+
if (!normalized) {
|
|
46
|
+
return '[masque]';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const fingerprint = createHash('sha256')
|
|
50
|
+
.update(normalized)
|
|
51
|
+
.digest('hex')
|
|
52
|
+
.slice(0, 8);
|
|
53
|
+
|
|
54
|
+
return `[masque:${fingerprint}]`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function buildTokenEntries({entries, currentToken, entryPathConfig}) {
|
|
58
|
+
const entryPath = entryPathConfig || {};
|
|
59
|
+
const graceTtlMs = computeTokenTtlMs(entryPath.graceMin);
|
|
60
|
+
const rotateTtlMs = Math.max(60_000, Number(entryPath.rotateMin || 0) * 60_000);
|
|
61
|
+
const normalizedCurrentToken = String(currentToken || '').trim();
|
|
62
|
+
let currentTokenCreatedAt = null;
|
|
63
|
+
const tokenEntries = Array.from(entries || [], ([token, createdAt]) => {
|
|
64
|
+
if (token === normalizedCurrentToken) {
|
|
65
|
+
currentTokenCreatedAt = createdAt;
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const createdAtMs = Math.floor(Number(createdAt));
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
token: maskToken(token),
|
|
73
|
+
isCurrent: false,
|
|
74
|
+
createdAt: Number.isFinite(createdAtMs) ? new Date(createdAtMs).toISOString() : null,
|
|
75
|
+
expiresAt: Number.isFinite(createdAtMs) ? new Date(createdAtMs + graceTtlMs).toISOString() : null,
|
|
76
|
+
};
|
|
77
|
+
}).filter(Boolean);
|
|
78
|
+
|
|
79
|
+
if (!normalizedCurrentToken) {
|
|
80
|
+
return tokenEntries;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const currentTokenCreatedAtMs = Math.floor(Number(currentTokenCreatedAt));
|
|
84
|
+
const currentTokenExpiresAtMs = Number.isFinite(currentTokenCreatedAtMs)
|
|
85
|
+
? currentTokenCreatedAtMs + Math.max(graceTtlMs, rotateTtlMs)
|
|
86
|
+
: NaN;
|
|
87
|
+
|
|
88
|
+
tokenEntries.push({
|
|
89
|
+
token: maskToken(normalizedCurrentToken),
|
|
90
|
+
isCurrent: true,
|
|
91
|
+
createdAt: Number.isFinite(currentTokenCreatedAtMs) ? new Date(currentTokenCreatedAtMs).toISOString() : null,
|
|
92
|
+
expiresAt: Number.isFinite(currentTokenExpiresAtMs) ? new Date(currentTokenExpiresAtMs).toISOString() : null,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return tokenEntries;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function createServerInfoRouter(services) {
|
|
99
|
+
const router = express.Router();
|
|
100
|
+
|
|
101
|
+
router.get('/', (_req, res) => {
|
|
102
|
+
res.sendFile(path.join(publicDir, 'server-info.html'));
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
router.get('/data', async (_req, res) => {
|
|
106
|
+
const clients = getConnectedClients(services.getServer().io);
|
|
107
|
+
const rawConfig = services.getConfig();
|
|
108
|
+
const rawSystemConfig = services.getSystemConfig();
|
|
109
|
+
const config = redactSecrets(rawConfig);
|
|
110
|
+
const sysConfig = redactSecrets(rawSystemConfig);
|
|
111
|
+
const logs = getRecentLogs(250);
|
|
112
|
+
const version = readPackageVersion(packageJsonPath);
|
|
113
|
+
const tasks = services.getTaskManager().getTasksSnapshot();
|
|
114
|
+
const tokenEntries = services.getPersistence().entryTokenDao.loadEntryTokens();
|
|
115
|
+
const restarts = services.getPersistence().restartLogDao.listRecentRestartRecords(20);
|
|
116
|
+
const currentToken = services.getTokenManager().getToken();
|
|
117
|
+
const entryPathConfig = services.getSystemConfig().entryPath;
|
|
118
|
+
const daemon = await services.getApplicationDaemonService().getInfo();
|
|
119
|
+
const system = await services.getSystem().getInfo();
|
|
120
|
+
const tokens = buildTokenEntries({
|
|
121
|
+
entries: tokenEntries,
|
|
122
|
+
currentToken,
|
|
123
|
+
entryPathConfig,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
res.json({
|
|
127
|
+
version,
|
|
128
|
+
now: new Date().toISOString(),
|
|
129
|
+
onlineSince: new Date(services.getServer().serverStartedAt).toISOString(),
|
|
130
|
+
uptimeSec: Math.floor(process.uptime()),
|
|
131
|
+
clientsConnected: clients.length,
|
|
132
|
+
clients,
|
|
133
|
+
tasks,
|
|
134
|
+
tokens,
|
|
135
|
+
daemon,
|
|
136
|
+
system,
|
|
137
|
+
restarts,
|
|
138
|
+
config,
|
|
139
|
+
sysConfig,
|
|
140
|
+
logs,
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
return router;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export const __testables = {
|
|
147
|
+
buildTokenEntries,
|
|
148
|
+
redactSecrets,
|
|
149
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import {sendUnauthorizedResponse} from './unauthorized-response.js';
|
|
3
|
+
import {
|
|
4
|
+
PUBSUB_EVENT_SESSION_CREATED,
|
|
5
|
+
PUBSUB_SERVICE_SESSION
|
|
6
|
+
} from '../../services/pubsub/serviceEventConstants.js';
|
|
7
|
+
|
|
8
|
+
function isLocalAddress(value) {
|
|
9
|
+
const address = String(value || '').toLowerCase();
|
|
10
|
+
return (
|
|
11
|
+
address === '127.0.0.1'
|
|
12
|
+
|| address === '::1'
|
|
13
|
+
|| address === '::ffff:127.0.0.1'
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function getForwardedFor(req) {
|
|
18
|
+
const raw = String(req.headers?.['x-forwarded-for'] || '').split(',')[0].trim();
|
|
19
|
+
return raw || null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const createSessionCreationMiddleware = ({
|
|
23
|
+
cookieName,
|
|
24
|
+
cookieMaxAgeMs,
|
|
25
|
+
secureCookies = true,
|
|
26
|
+
}) => (req, res, next) => {
|
|
27
|
+
res.createSession = (token) => {
|
|
28
|
+
res.cookie(cookieName, token,
|
|
29
|
+
{
|
|
30
|
+
signed: true,
|
|
31
|
+
httpOnly: true,
|
|
32
|
+
secure: secureCookies,
|
|
33
|
+
sameSite: 'lax',
|
|
34
|
+
maxAge: cookieMaxAgeMs,
|
|
35
|
+
path: '/',
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
next();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function createSessionGuard(services, {
|
|
42
|
+
onUnauthorized = sendUnauthorizedResponse,
|
|
43
|
+
} = {}) {
|
|
44
|
+
return (req, res, next) => {
|
|
45
|
+
const tokenManager = services.getTokenManager();
|
|
46
|
+
const cookieName = services.getSystemConfig().session.cookieName;
|
|
47
|
+
const forwarded = getForwardedFor(req);
|
|
48
|
+
const clientIp = forwarded || req.ip || req.socket?.remoteAddress;
|
|
49
|
+
const allowBypass = isLocalAddress(clientIp);
|
|
50
|
+
|
|
51
|
+
const token = req.signedCookies && req.signedCookies[cookieName];
|
|
52
|
+
if (!allowBypass && !tokenManager.isValid(token)) {
|
|
53
|
+
onUnauthorized(req, res);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
req.sessionToken = token;
|
|
57
|
+
next();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function createSessionRouter(services) {
|
|
62
|
+
const router = express.Router();
|
|
63
|
+
|
|
64
|
+
router.get('/:token', (req, res) => {
|
|
65
|
+
const tokenManager = services.getTokenManager();
|
|
66
|
+
const token = req.params.token;
|
|
67
|
+
if (!tokenManager.isValid(token)) {
|
|
68
|
+
sendUnauthorizedResponse(req, res);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const forwarded = getForwardedFor(req);
|
|
72
|
+
const clientIp = forwarded || req.ip || req.socket?.remoteAddress || '';
|
|
73
|
+
services.getEvents().publishEvent(PUBSUB_SERVICE_SESSION, PUBSUB_EVENT_SESSION_CREATED, {
|
|
74
|
+
address: String(clientIp || '').trim(),
|
|
75
|
+
token,
|
|
76
|
+
});
|
|
77
|
+
res.createSession(token);
|
|
78
|
+
res.redirect('/');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// router.post('/:token', (req, res, next) => {
|
|
82
|
+
// req.signedCookies = {
|
|
83
|
+
// ...req.signedCookies,
|
|
84
|
+
// [services.getSystemConfig().session.cookieName]: req.params.token,
|
|
85
|
+
// };
|
|
86
|
+
// next();
|
|
87
|
+
// }, postSessionGuard, (req, res) => {
|
|
88
|
+
// res.createSession(req.params.token);
|
|
89
|
+
// res.status(204).end();
|
|
90
|
+
// });
|
|
91
|
+
|
|
92
|
+
return router;
|
|
93
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
function getUnauthorizedPageHtml() {
|
|
2
|
+
return `<!doctype html>
|
|
3
|
+
<html lang="fr">
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
+
<title>Acces expire</title>
|
|
8
|
+
<style>
|
|
9
|
+
:root {
|
|
10
|
+
color-scheme: dark;
|
|
11
|
+
--bg: #101417;
|
|
12
|
+
--panel: rgba(19, 27, 33, 0.92);
|
|
13
|
+
--fg: #f0f4f7;
|
|
14
|
+
--muted: rgba(240, 244, 247, 0.78);
|
|
15
|
+
--accent: #4bd4ff;
|
|
16
|
+
--danger: #ff8f8f;
|
|
17
|
+
}
|
|
18
|
+
* { box-sizing: border-box; }
|
|
19
|
+
body {
|
|
20
|
+
margin: 0;
|
|
21
|
+
min-height: 100vh;
|
|
22
|
+
display: grid;
|
|
23
|
+
place-items: center;
|
|
24
|
+
padding: 24px;
|
|
25
|
+
background: radial-gradient(circle at 20% 10%, #1f2e3a, var(--bg));
|
|
26
|
+
color: var(--fg);
|
|
27
|
+
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
|
28
|
+
}
|
|
29
|
+
main {
|
|
30
|
+
width: min(100%, 460px);
|
|
31
|
+
padding: 28px 24px;
|
|
32
|
+
border-radius: 18px;
|
|
33
|
+
border: 1px solid rgba(255, 255, 255, 0.14);
|
|
34
|
+
background: var(--panel);
|
|
35
|
+
box-shadow: 0 18px 48px rgba(0, 0, 0, 0.35);
|
|
36
|
+
}
|
|
37
|
+
.eyebrow {
|
|
38
|
+
margin: 0 0 12px;
|
|
39
|
+
color: var(--danger);
|
|
40
|
+
font-size: 0.82rem;
|
|
41
|
+
font-weight: 700;
|
|
42
|
+
letter-spacing: 0.08em;
|
|
43
|
+
text-transform: uppercase;
|
|
44
|
+
}
|
|
45
|
+
h1 {
|
|
46
|
+
margin: 0 0 10px;
|
|
47
|
+
font-size: clamp(1.6rem, 5vw, 2rem);
|
|
48
|
+
line-height: 1.1;
|
|
49
|
+
}
|
|
50
|
+
p {
|
|
51
|
+
margin: 0 0 12px;
|
|
52
|
+
color: var(--muted);
|
|
53
|
+
line-height: 1.5;
|
|
54
|
+
}
|
|
55
|
+
</style>
|
|
56
|
+
</head>
|
|
57
|
+
<body>
|
|
58
|
+
<main>
|
|
59
|
+
<h1>Connexion expiree</h1>
|
|
60
|
+
<p>Rescannez le code QR du serveur.</p>
|
|
61
|
+
</main>
|
|
62
|
+
</body>
|
|
63
|
+
</html>`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function sendUnauthorizedResponse(req, res) {
|
|
67
|
+
if (typeof req?.accepts === 'function' && req.accepts('html')) {
|
|
68
|
+
res.status(401).type('text/html').send(getUnauthorizedPageHtml());
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
res.status(401).type('text/plain').send('Unauthorized');
|
|
73
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {createLogger} from "../../application/logger.js";
|
|
2
|
+
import {
|
|
3
|
+
PUBSUB_EVENT_SOCKET_CLIENT_DISCONNECTED,
|
|
4
|
+
PUBSUB_SERVICE_SOCKET
|
|
5
|
+
} from "../../services/pubsub/serviceEventConstants.js";
|
|
6
|
+
|
|
7
|
+
let log;
|
|
8
|
+
function getModuleLog() {
|
|
9
|
+
log ??= createLogger('socket');
|
|
10
|
+
return log;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function createConnectionRegistrar({events}) {
|
|
14
|
+
const log = getModuleLog();
|
|
15
|
+
return (socket) => {
|
|
16
|
+
socket.on('disconnect', () => {
|
|
17
|
+
log.info({socketId: socket.id}, 'Client déconnecté');
|
|
18
|
+
events.publishEvent(PUBSUB_SERVICE_SOCKET, PUBSUB_EVENT_SOCKET_CLIENT_DISCONNECTED, {
|
|
19
|
+
clientId: socket.id,
|
|
20
|
+
});
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
function isLocalAddress(value) {
|
|
2
|
+
const address = String(value || '').toLowerCase();
|
|
3
|
+
return (
|
|
4
|
+
address === '127.0.0.1'
|
|
5
|
+
|| address === '::1'
|
|
6
|
+
|| address === '::ffff:127.0.0.1'
|
|
7
|
+
);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function getForwardedFor(request) {
|
|
11
|
+
const raw = String(request?.headers?.['x-forwarded-for'] || '').split(',')[0].trim();
|
|
12
|
+
return raw || null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function createSocketSessionAuthMiddleware(services) {
|
|
16
|
+
function createUnauthorizedError() {
|
|
17
|
+
const error = new Error('unauthorized');
|
|
18
|
+
error.data = {
|
|
19
|
+
code: 'ENTRY_TOKEN_INVALID',
|
|
20
|
+
message: 'Rescannez le code QR du serveur.',
|
|
21
|
+
};
|
|
22
|
+
return error;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function authorizeSocket(socket, next) {
|
|
26
|
+
const forwarded = getForwardedFor(socket.request);
|
|
27
|
+
const remoteAddress = forwarded || socket.request?.socket?.remoteAddress;
|
|
28
|
+
if (isLocalAddress(remoteAddress)) {
|
|
29
|
+
next();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const systemConfig = services.getSystemConfig();
|
|
34
|
+
const tokenManager = services.getTokenManager();
|
|
35
|
+
const cookieName = systemConfig.session.cookieName;
|
|
36
|
+
|
|
37
|
+
const token = socket.request?.signedCookies?.[cookieName];
|
|
38
|
+
if (!tokenManager?.isValid?.(token)) {
|
|
39
|
+
next(createUnauthorizedError());
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
socket.sessionToken = token;
|
|
44
|
+
next();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
return authorizeSocket;
|
|
49
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { REMOTE_EVENT_ADMIN_RESULT } from '../../../utils/remoteCommands.js';
|
|
2
|
+
|
|
3
|
+
export function createSocketActionResponder({ socket, eventName = REMOTE_EVENT_ADMIN_RESULT }) {
|
|
4
|
+
return function respondAction(action, result = {}) {
|
|
5
|
+
socket.emit(eventName, {
|
|
6
|
+
action,
|
|
7
|
+
ok: Boolean(result.ok),
|
|
8
|
+
message: result.message,
|
|
9
|
+
openUrl: result.openUrl,
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {createLogger} from '../../application/logger.js';
|
|
2
|
+
|
|
3
|
+
let log;
|
|
4
|
+
function getModuleLog() {
|
|
5
|
+
log ??= createLogger('socket:timestamp');
|
|
6
|
+
return log;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function socketTimestampGuardMiddleware({
|
|
10
|
+
maxEventAgeMs = 1200,
|
|
11
|
+
maxClockSkewMs = 5 * 60 * 1000,
|
|
12
|
+
socketId,
|
|
13
|
+
} = {}) {
|
|
14
|
+
const log = getModuleLog();
|
|
15
|
+
let observedClockOffsetMs = null;
|
|
16
|
+
|
|
17
|
+
return function enforceSocketEventTimestamp(packet, next) {
|
|
18
|
+
const [, payload] = packet;
|
|
19
|
+
const ts = payload && typeof payload === 'object'
|
|
20
|
+
? Number(payload.ts)
|
|
21
|
+
: NaN;
|
|
22
|
+
|
|
23
|
+
if (!Number.isFinite(ts)) {
|
|
24
|
+
log.warn({ socketId, event: packet[0] }, 'Message socket sans timestamp');
|
|
25
|
+
next(new Error('missing_timestamp'));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const rawDeltaMs = Date.now() - ts;
|
|
30
|
+
if (observedClockOffsetMs == null && Math.abs(rawDeltaMs) <= maxClockSkewMs) {
|
|
31
|
+
observedClockOffsetMs = rawDeltaMs;
|
|
32
|
+
log.info({ socketId, event: packet[0], observedClockOffsetMs }, 'Calibration horloge socket');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const ageMs = rawDeltaMs - (observedClockOffsetMs || 0);
|
|
36
|
+
if (ageMs > maxEventAgeMs) {
|
|
37
|
+
log.warn({
|
|
38
|
+
socketId,
|
|
39
|
+
event: packet[0],
|
|
40
|
+
ageMs,
|
|
41
|
+
rawDeltaMs,
|
|
42
|
+
observedClockOffsetMs,
|
|
43
|
+
maxEventAgeMs,
|
|
44
|
+
}, 'Message socket expiré');
|
|
45
|
+
next(new Error('stale_event'));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
next();
|
|
50
|
+
};
|
|
51
|
+
}
|
package/server/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {createServicesRegistry} from './services/createServicesRegistry.js';
|
|
2
|
+
import {
|
|
3
|
+
bootstrapLogger,
|
|
4
|
+
} from './application/logger.js';
|
|
5
|
+
import {createApplicationLifecycle} from './application/createApplicationLifecycle.js';
|
|
6
|
+
|
|
7
|
+
export async function startServer() {
|
|
8
|
+
const services = await createServicesRegistry();
|
|
9
|
+
bootstrapLogger();
|
|
10
|
+
const lifecycle = createApplicationLifecycle(services);
|
|
11
|
+
return lifecycle.start();
|
|
12
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import {createStaticShareRouter} from '../connection/api/client.router.js';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import {
|
|
4
|
+
clientDir,
|
|
5
|
+
projectRoot,
|
|
6
|
+
publicDir,
|
|
7
|
+
sharedUtilsDir
|
|
8
|
+
} from '../utils/paths.js';
|
|
9
|
+
import {
|
|
10
|
+
createSessionCreationMiddleware,
|
|
11
|
+
createSessionGuard,
|
|
12
|
+
createSessionRouter,
|
|
13
|
+
} from '../connection/api/session.middleware.js';
|
|
14
|
+
import {createQrPageHandler} from '../connection/api/qr-page.handler.js';
|
|
15
|
+
import {createAdminUiRouter} from "./createAdminUiRouter.js";
|
|
16
|
+
import {createAdminApiRouter} from "./createAdminApiRouter.js";
|
|
17
|
+
import { createRemotesRouter } from '../connection/api/remotes.router.js';
|
|
18
|
+
import {readPackageVersion} from '../utils/env.js';
|
|
19
|
+
import {createLogger} from '../application/logger.js';
|
|
20
|
+
|
|
21
|
+
const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
22
|
+
|
|
23
|
+
export function bootstrapApi(services) {
|
|
24
|
+
const {
|
|
25
|
+
getTokenManager,
|
|
26
|
+
getSystemConfig,
|
|
27
|
+
getServer,
|
|
28
|
+
} = services;
|
|
29
|
+
|
|
30
|
+
const {
|
|
31
|
+
app,
|
|
32
|
+
cookieParser
|
|
33
|
+
} = getServer();
|
|
34
|
+
|
|
35
|
+
const systemConfig = getSystemConfig();
|
|
36
|
+
const log = createLogger('createApp');
|
|
37
|
+
|
|
38
|
+
log.debug({
|
|
39
|
+
httpsEnabled: Boolean(systemConfig.https.enabled),
|
|
40
|
+
cookieName: systemConfig.session.cookieName,
|
|
41
|
+
entryPathEnabled: Boolean(systemConfig.entryPath.enabled),
|
|
42
|
+
}, 'Initialisation API Express');
|
|
43
|
+
|
|
44
|
+
if (!systemConfig.https.enabled) {
|
|
45
|
+
log.warn('HTTPS=false: cookie session envoyé sans attribut Secure (moins sécuritaire).');
|
|
46
|
+
}
|
|
47
|
+
app.set('trust proxy', 'loopback');
|
|
48
|
+
|
|
49
|
+
app.use(cookieParser);
|
|
50
|
+
|
|
51
|
+
app.use(createSessionCreationMiddleware({
|
|
52
|
+
cookieName: systemConfig.session.cookieName,
|
|
53
|
+
cookieMaxAgeMs: Math.max(1, systemConfig.session.cookieMaxAgeDays) * 24 * 60 * 60 * 1000,
|
|
54
|
+
secureCookies: systemConfig.https.enabled,
|
|
55
|
+
}));
|
|
56
|
+
|
|
57
|
+
app.use('/api/sessions', createSessionRouter(services));
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
app.use(createSessionGuard(services));
|
|
61
|
+
|
|
62
|
+
app.get('/', (req, res, next) => {
|
|
63
|
+
if (req.sessionToken) {
|
|
64
|
+
res.createSession(getTokenManager().getToken());
|
|
65
|
+
}
|
|
66
|
+
next();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
app.use(createStaticShareRouter({
|
|
70
|
+
publicDir,
|
|
71
|
+
clientDir,
|
|
72
|
+
sharedUtilsDir
|
|
73
|
+
}));
|
|
74
|
+
|
|
75
|
+
app.get('/qr', createQrPageHandler(services));
|
|
76
|
+
app.use('/api/remotes', createRemotesRouter(services));
|
|
77
|
+
app.use('/api/admin', createAdminApiRouter(services));
|
|
78
|
+
app.use('/ui/admin', createAdminUiRouter(services));
|
|
79
|
+
log.trace('Routes API enregistrees');
|
|
80
|
+
|
|
81
|
+
app.get('/health', (_req, res) => {
|
|
82
|
+
res.json({
|
|
83
|
+
ok: true,
|
|
84
|
+
version: readPackageVersion(packageJsonPath),
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import {createSocketSessionAuthMiddleware} from '../connection/socket/createSocketSessionAuthMiddleware.js';
|
|
2
|
+
import {createSocketActionRegistrars} from './createSocketActionRegistrars.js';
|
|
3
|
+
import {socketTimestampGuardMiddleware} from "../connection/socket/socket.timestamp-middleware.js";
|
|
4
|
+
import { hasRecentRestart } from '../remotes/admin/notifyIfRestarted.js';
|
|
5
|
+
import {
|
|
6
|
+
PUBSUB_EVENT_SOCKET_CLIENT_CONNECTED,
|
|
7
|
+
PUBSUB_SERVICE_SOCKET
|
|
8
|
+
} from "../services/pubsub/serviceEventConstants.js";
|
|
9
|
+
import { REMOTE_EVENT_SYSTEM_RELOAD } from '../../utils/remoteCommands.js';
|
|
10
|
+
import {createLogger} from '../application/logger.js';
|
|
11
|
+
|
|
12
|
+
function broadcast(...functions) {
|
|
13
|
+
return (...args) => functions.flatMap(f => f).map(f => f(...args));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function createNotificationHandler(services) {
|
|
17
|
+
const events = services.getEvents();
|
|
18
|
+
const log = createLogger('socket:timestamp');
|
|
19
|
+
|
|
20
|
+
return socket => {
|
|
21
|
+
log.info({socketId: socket.id}, 'Client connecté');
|
|
22
|
+
events.publishEvent(PUBSUB_SERVICE_SOCKET, PUBSUB_EVENT_SOCKET_CLIENT_CONNECTED, {
|
|
23
|
+
clientId: socket.id,
|
|
24
|
+
});
|
|
25
|
+
if (hasRecentRestart()) {
|
|
26
|
+
socket.emit(REMOTE_EVENT_SYSTEM_RELOAD, {
|
|
27
|
+
reason: 'service-restarted',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function createSocketGuardMiddleware(services) {
|
|
34
|
+
const {
|
|
35
|
+
getSystemConfig,
|
|
36
|
+
} = services;
|
|
37
|
+
|
|
38
|
+
const maxEventAgeMs = getSystemConfig().session.socketEventMaxAgeMs;
|
|
39
|
+
|
|
40
|
+
return (socket, next) => {
|
|
41
|
+
socket.use(socketTimestampGuardMiddleware({
|
|
42
|
+
maxEventAgeMs,
|
|
43
|
+
socketId: socket.id,
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
// ... other guards here
|
|
47
|
+
|
|
48
|
+
next();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function createActionHandlers(services) {
|
|
53
|
+
const socketActionRegistrars = createSocketActionRegistrars(services);
|
|
54
|
+
return socket => {
|
|
55
|
+
for (let register of socketActionRegistrars) {
|
|
56
|
+
register(socket);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function bootstrapSocket(services) {
|
|
62
|
+
const {getServer} = services;
|
|
63
|
+
const log = createLogger('socket:bootstrap');
|
|
64
|
+
|
|
65
|
+
const {io, cookieParser} = getServer();
|
|
66
|
+
log.debug('Initialisation Socket.IO');
|
|
67
|
+
|
|
68
|
+
io.engine.use((...args) => cookieParser(...args));
|
|
69
|
+
|
|
70
|
+
io.use(createSocketSessionAuthMiddleware(services));
|
|
71
|
+
io.use(createSocketGuardMiddleware(services));
|
|
72
|
+
log.trace('Middlewares Socket.IO enregistres');
|
|
73
|
+
|
|
74
|
+
io.on('connection', broadcast(
|
|
75
|
+
createNotificationHandler(services),
|
|
76
|
+
createActionHandlers(services)
|
|
77
|
+
));
|
|
78
|
+
log.debug('Handlers Socket.IO enregistres');
|
|
79
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import {createServerInfoRouter} from "../connection/api/server-info.router.js";
|
|
3
|
+
import {createAdminConfigsRouter} from "../connection/api/admin-configs.router.js";
|
|
4
|
+
import {createAdminConfigActionsRouter} from "../connection/api/admin-actions.router.js";
|
|
5
|
+
import {createAdminSubsRouter} from "../connection/api/admin-subs.router.js";
|
|
6
|
+
import {createAdminRemotesRouter} from '../connection/api/admin-remotes.router.js';
|
|
7
|
+
|
|
8
|
+
export function createAdminApiRouter(services) {
|
|
9
|
+
const router = express.Router();
|
|
10
|
+
|
|
11
|
+
router.use('/server-info', createServerInfoRouter(services));
|
|
12
|
+
|
|
13
|
+
router.use('/configs', createAdminConfigsRouter(services));
|
|
14
|
+
|
|
15
|
+
router.use('/remotes', createAdminRemotesRouter(services));
|
|
16
|
+
|
|
17
|
+
router.use('/subs', createAdminSubsRouter(services));
|
|
18
|
+
|
|
19
|
+
router.use('/', createAdminConfigActionsRouter(services));
|
|
20
|
+
|
|
21
|
+
return router;
|
|
22
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import {publicDir} from "../utils/paths.js";
|
|
4
|
+
|
|
5
|
+
export function createAdminUiRouter(_services) {
|
|
6
|
+
const router = express.Router();
|
|
7
|
+
|
|
8
|
+
router.get('/config', (_req, res) => {
|
|
9
|
+
res.sendFile(path.join(publicDir, 'admin-config.html'));
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
router.get('/server-info', (_req, res) => {
|
|
13
|
+
res.sendFile(path.join(publicDir, 'server-info.html'));
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
router.get('/preferences', (_req, res) => {
|
|
17
|
+
res.sendFile(path.join(publicDir, 'preferences.html'));
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return router;
|
|
21
|
+
}
|