iot-agent/socket/socketHandler.js
2025-08-03 23:07:33 +05:30

111 lines
3.2 KiB
JavaScript

const jwt = require('jsonwebtoken');
const logger = require('../utils/logger');
const redis = require('../config/redis');
const database = require('../config/database');
const socketHandler = (io) => {
// Authentication middleware for Socket.IO
io.use(async (socket, next) => {
try {
const token = socket.handshake.auth.token || socket.handshake.headers.authorization;
if (!token) {
return next(new Error('Authentication error: No token provided'));
}
const cleanToken = token.replace('Bearer ', '');
const decoded = jwt.verify(cleanToken, process.env.JWT_SECRET);
// Verify user session
const session = await redis.getUserSession(decoded.id);
if (!session) {
return next(new Error('Authentication error: Session expired'));
}
// Get user info
const [users] = await database.query(
'SELECT id, username, email, role FROM users WHERE id = ? AND status = "active"',
[decoded.id]
);
if (users.length === 0) {
return next(new Error('Authentication error: User not found'));
}
socket.user = users[0];
next();
} catch (error) {
logger.error('Socket authentication failed:', error);
next(new Error('Authentication error: Invalid token'));
}
});
io.on('connection', (socket) => {
logger.info(`User connected: ${socket.user.username} (${socket.id})`);
// Join user to their personal room
socket.join(`user:${socket.user.id}`);
// Join admin users to admin room
if (socket.user.role === 'admin') {
socket.join('admin');
}
// Handle device data updates
socket.on('subscribe_device', (deviceId) => {
socket.join(`device:${deviceId}`);
logger.info(`User ${socket.user.username} subscribed to device ${deviceId}`);
});
socket.on('unsubscribe_device', (deviceId) => {
socket.leave(`device:${deviceId}`);
logger.info(`User ${socket.user.username} unsubscribed from device ${deviceId}`);
});
// Handle alert subscriptions
socket.on('subscribe_alerts', () => {
socket.join('alerts');
logger.info(`User ${socket.user.username} subscribed to alerts`);
});
socket.on('unsubscribe_alerts', () => {
socket.leave('alerts');
logger.info(`User ${socket.user.username} unsubscribed from alerts`);
});
// Handle disconnect
socket.on('disconnect', () => {
logger.info(`User disconnected: ${socket.user.username} (${socket.id})`);
});
});
// Export socket functions for use in other modules
return {
// Emit device data updates
emitDeviceData: (deviceId, data) => {
io.to(`device:${deviceId}`).emit('device_data_update', {
deviceId,
data,
timestamp: new Date().toISOString()
});
},
// Emit alerts
emitAlert: (alert) => {
io.to('alerts').emit('new_alert', {
...alert,
timestamp: new Date().toISOString()
});
},
// Emit to admin users
emitToAdmin: (event, data) => {
io.to('admin').emit(event, {
...data,
timestamp: new Date().toISOString()
});
}
};
};
module.exports = socketHandler;