diff --git a/scripts/setup-desktop.sh b/scripts/setup-desktop.sh index fc8d24db..781bcf64 100755 --- a/scripts/setup-desktop.sh +++ b/scripts/setup-desktop.sh @@ -5,7 +5,7 @@ set -euo pipefail # Run as the user who will own the VNC session (not root). # Usage: ./scripts/setup-desktop.sh [resolution] -VNC_PASS="${1:-$(head -c 6 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9' | head -c 8)}" +VNC_PASS="${1:-$(head -c 32 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9' | head -c 8)}" RESOLUTION="${2:-1920x1080}" USER_NAME="$(whoami)" ENV_FILE="$(cd "$(dirname "$0")/.." && pwd)/.env" @@ -51,6 +51,10 @@ echo "[3/8] Configuring VNC password..." mkdir -p ~/.vnc echo "$VNC_PASS" | vncpasswd -f > ~/.vnc/passwd chmod 600 ~/.vnc/passwd +# Plain-text password + port for the Officer server to read +echo -n "$VNC_PASS" > ~/.vnc/password +chmod 600 ~/.vnc/password +echo "5901" > ~/.vnc/port echo " Done." # --- Step 4: Create xstartup --- diff --git a/src/servers/api/desktop/rest.ts b/src/servers/api/desktop/rest.ts index 3da12a54..7b786b10 100644 --- a/src/servers/api/desktop/rest.ts +++ b/src/servers/api/desktop/rest.ts @@ -1,9 +1,11 @@ import { createRouter } from '../../create-router'; +import { getVncPassword } from './vnc-config'; export const desktopRouter = createRouter(); -desktopRouter.get('/vnc-password', (ctx) => { - const password = process.env.VNC_PASSWORD; +desktopRouter.get('/vnc-password', async (ctx) => { + const user = ctx.get('user'); + const password = await getVncPassword(user.email, user.role); if (!password) { return ctx.json({ error: 'VNC password not configured' }, 500); } diff --git a/src/servers/api/desktop/vnc-config.ts b/src/servers/api/desktop/vnc-config.ts new file mode 100644 index 00000000..3b0873f2 --- /dev/null +++ b/src/servers/api/desktop/vnc-config.ts @@ -0,0 +1,22 @@ +import { join } from 'node:path'; +import { getHomeDir } from '@@/data-path'; + +function getVncDir(email: string, role: string | null): string { + const home = role === 'Super Admin' && process.env.HOME_DIR + ? process.env.HOME_DIR + : getHomeDir(email); + return join(home, '.vnc'); +} + +export async function getVncPassword(email: string, role: string | null): Promise { + const file = Bun.file(join(getVncDir(email, role), 'password')); + if (!(await file.exists())) return null; + return (await file.text()).trim(); +} + +export async function getVncPort(email: string, role: string | null): Promise { + const file = Bun.file(join(getVncDir(email, role), 'port')); + if (!(await file.exists())) return 5901; + const port = parseInt((await file.text()).trim(), 10); + return isNaN(port) ? 5901 : port; +} diff --git a/src/servers/api/desktop/websocket.ts b/src/servers/api/desktop/websocket.ts index e212e00d..f51908c4 100644 --- a/src/servers/api/desktop/websocket.ts +++ b/src/servers/api/desktop/websocket.ts @@ -1,5 +1,6 @@ import type { ServerWebSocket } from 'bun'; import type { Socket } from 'bun'; +import { getVncPort } from './vnc-config'; type WSData = { userId: number; email: string; username: string; role: string; sandboxed: boolean; sessionId?: string }; @@ -8,8 +9,6 @@ type VncSession = { pendingMessages: Buffer[]; }; -const VNC_PORT = Number(process.env.VNC_PORT || 5901); - const sessions = new Map, VncSession>(); export const desktopWebsocket = { @@ -19,13 +18,14 @@ export const desktopWebsocket = { return; } + const port = await getVncPort(ws.data.email, ws.data.role); const session: VncSession = { tcpSocket: null, pendingMessages: [] }; sessions.set(ws, session); try { const tcpSocket = await Bun.connect({ hostname: '127.0.0.1', - port: VNC_PORT, + port, socket: { data(_socket, data) { try {