Add node location access RPCs and operator visibility
This commit is contained in:
+45
-3
@@ -97,6 +97,7 @@ export interface GatewayServerConfig {
|
||||
enabled: boolean;
|
||||
allowedRoles: string[];
|
||||
featureGates: Record<string, boolean>;
|
||||
locationEnabled?: boolean;
|
||||
};
|
||||
/** Optional pairing manager for DM pairing code management via gateway. */
|
||||
pairingManager?: PairingManager;
|
||||
@@ -185,6 +186,36 @@ export class GatewayServer {
|
||||
getPresence: channelRegistry
|
||||
? (opts) => channelRegistry.getPresence(opts)
|
||||
: undefined,
|
||||
getNodeLocations: ({ role, nodeId, limit } = {}) => {
|
||||
const entries: Array<{
|
||||
nodeId: string;
|
||||
role: string;
|
||||
connectionId: string;
|
||||
location: NonNullable<NodeConnectionState['location']>;
|
||||
}> = [];
|
||||
for (const [connectionId, state] of this.connectionStateMap.entries()) {
|
||||
if (!state.node || !state.location) {
|
||||
continue;
|
||||
}
|
||||
if (role && state.node.role !== role) {
|
||||
continue;
|
||||
}
|
||||
if (nodeId && state.node.nodeId !== nodeId) {
|
||||
continue;
|
||||
}
|
||||
entries.push({
|
||||
nodeId: state.node.nodeId,
|
||||
role: state.node.role,
|
||||
connectionId,
|
||||
location: state.location,
|
||||
});
|
||||
}
|
||||
const sorted = entries.sort((a, b) => b.location.receivedAt - a.location.receivedAt);
|
||||
if (typeof limit === 'number' && Number.isFinite(limit) && limit > 0) {
|
||||
return sorted.slice(0, Math.floor(limit));
|
||||
}
|
||||
return sorted;
|
||||
},
|
||||
getUsage: () => ({
|
||||
totalSessions: this.config.sessionManager.listSessions().length,
|
||||
activeConnections: this.sessionBridge.connectionCount,
|
||||
@@ -279,6 +310,7 @@ export class GatewayServer {
|
||||
|
||||
const nodeHandlers = createNodeHandlers({
|
||||
enabled: this.config.nodes?.enabled ?? false,
|
||||
locationEnabled: this.config.nodes?.locationEnabled ?? false,
|
||||
allowedRoles: this.config.nodes?.allowedRoles ?? [],
|
||||
featureGates: this.config.nodes?.featureGates ?? {},
|
||||
getConnectionState: (connectionId) => this.connectionStateMap.get(connectionId),
|
||||
@@ -292,6 +324,16 @@ export class GatewayServer {
|
||||
node: registration,
|
||||
});
|
||||
},
|
||||
setNodeLocation: (connectionId, location) => {
|
||||
const existing = this.connectionStateMap.get(connectionId);
|
||||
if (!existing) {
|
||||
return;
|
||||
}
|
||||
this.connectionStateMap.set(connectionId, {
|
||||
...existing,
|
||||
location,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// Config handlers (only if config object is provided)
|
||||
@@ -635,9 +677,9 @@ export class GatewayServer {
|
||||
nodeRole: this.connectionStateMap.get(connectionId)?.node?.role,
|
||||
allowedRoles: this.config.nodes?.allowedRoles ?? [],
|
||||
roleScopes: {
|
||||
companion: ['node.capabilities.get'],
|
||||
observer: ['node.capabilities.get'],
|
||||
automation: ['node.capabilities.get'],
|
||||
companion: ['node.capabilities.get', 'node.location.set', 'node.location.get'],
|
||||
observer: ['node.capabilities.get', 'node.location.get'],
|
||||
automation: ['node.capabilities.get', 'node.location.get'],
|
||||
},
|
||||
});
|
||||
if (!nodeAuth.authenticated) {
|
||||
|
||||
Reference in New Issue
Block a user