diff --git a/src/socket/__tests__/socketuser.test.js b/src/socket/__tests__/socketuser.test.js index f812907..cf6f564 100644 --- a/src/socket/__tests__/socketuser.test.js +++ b/src/socket/__tests__/socketuser.test.js @@ -335,5 +335,24 @@ describe('SocketUser', () => { socketUser.notificationManager.removeAllListeners ).toHaveBeenCalled(); }); + + it('should cancel tracked scan sessions', async () => { + socketUser.scanSessions.set('session-1', 'host-1'); + socketUser.scanSessions.set('session-2', 'host-2'); + + await socketUser.handleDisconnect(); + + expect(socketUser.actionManager.sendObjectAction).toHaveBeenCalledWith( + 'host-1', + 'host', + { type: 'scanNetworkStop', data: { sessionId: 'session-1' } } + ); + expect(socketUser.actionManager.sendObjectAction).toHaveBeenCalledWith( + 'host-2', + 'host', + { type: 'scanNetworkStop', data: { sessionId: 'session-2' } } + ); + expect(socketUser.scanSessions.size).toBe(0); + }); }); }); diff --git a/src/socket/socketuser.js b/src/socket/socketuser.js index f6b4c5f..977062b 100644 --- a/src/socket/socketuser.js +++ b/src/socket/socketuser.js @@ -35,6 +35,7 @@ export class SocketUser { this.serverManager = new ServerManager(this); this.userSettingsManager = new UserSettingsManager(this); this.keycloakAuth = new KeycloakAuth(); + this.scanSessions = new Map(); this.setupSocketEventHandlers(); } @@ -352,15 +353,52 @@ export class SocketUser { } async handleObjectActionEvent(data, callback) { + const action = data?.action; + const sessionId = action?.data?.sessionId; + + if ( + data?.objectType === 'host' && + action?.type === 'scanNetwork' && + sessionId + ) { + this.scanSessions.set(sessionId, data._id); + } + + if (action?.type === 'scanNetworkStop' && sessionId) { + this.scanSessions.delete(sessionId); + } + await this.actionManager.sendObjectAction( data._id, data.objectType, - data.action, + action, callback ); } + async cancelScanSessions() { + const sessions = Array.from(this.scanSessions.entries()); + this.scanSessions.clear(); + + if (sessions.length === 0) { + return; + } + + logger.info('Cancelling scan sessions on user disconnect:', sessions.length); + + await Promise.all( + sessions.map(([sessionId, hostId]) => + this.actionManager.sendObjectAction(hostId, 'host', { + type: 'scanNetworkStop', + data: { sessionId } + }) + ) + ); + } + async handleDisconnect() { + await this.cancelScanSessions(); + if (this.user?._id) { const userId = this.user._id.toString(); for (const activityKey of this.trackedActivities) {