File size: 1,618 Bytes
149698e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import type { Server as SocketIOServer } from 'socket.io';
import jwt from 'jsonwebtoken';
import { config } from '../config/env.js';
import pino from 'pino';

const logger = pino({ level: 'info', transport: { target: 'pino-pretty', options: { colorize: true } } });

export function setupScanEvents(io: SocketIOServer) {
  io.on('connection', (socket) => {
    // Authenticate the socket connection using JWT from cookies or auth query
    let userId: string | null = null;

    try {
      const cookieHeader = socket.handshake.headers.cookie || '';
      const tokenMatch = cookieHeader.match(/token=([^;]+)/);
      const token = tokenMatch?.[1] || (socket.handshake.auth?.token as string);

      if (token) {
        const payload = jwt.verify(token, config.JWT_SECRET) as { userId: string };
        userId = payload.userId;
        // Join user-specific room so events are scoped
        socket.join(`user:${userId}`);
        logger.info({ socketId: socket.id, userId }, 'Client authenticated and joined user room');
      } else {
        logger.warn({ socketId: socket.id }, 'Client connected without auth token');
      }
    } catch (err) {
      logger.warn({ socketId: socket.id }, 'Client connected with invalid token');
    }

    socket.on('scan:join', (jobId: string) => {
      socket.join(`scan:${jobId}`);
      logger.info({ socketId: socket.id, jobId }, 'Client joined scan room');
    });

    socket.on('scan:leave', (jobId: string) => {
      socket.leave(`scan:${jobId}`);
    });

    socket.on('disconnect', () => {
      logger.info(`Client disconnected: ${socket.id}`);
    });
  });
}