import log4js from 'log4js'; // Load configuration import { loadConfig } from '../config.js'; import { createAuthMiddleware, KeycloakAuth } from '../auth/auth.js'; import { generateHostOTP } from '../utils.js'; import { LockManager } from '../lock/lockmanager.js'; import { UpdateManager } from '../updates/updatemanager.js'; import { ActionManager } from '../actions/actionmanager.js'; import { EventManager } from '../events/eventmanager.js'; import { StatsManager } from '../stats/statsmanager.js'; const config = loadConfig(); const logger = log4js.getLogger('Socket User'); logger.level = config.server.logLevel; export class SocketUser { constructor(socket, socketManager) { this.socket = socket; this.authenticated = false; this.socketId = socket.id; this.id = null; this.user = null; this.socketManager = socketManager; this.lockManager = new LockManager(this); this.updateManager = new UpdateManager(this); this.actionManager = new ActionManager(this); this.eventManager = new EventManager(this); this.statsManager = new StatsManager(this); this.templateManager = socketManager.templateManager; this.keycloakAuth = new KeycloakAuth(); this.setupSocketEventHandlers(); } setupSocketEventHandlers() { this.socket.use(createAuthMiddleware(this)); this.socket.on('authenticate', this.handleAuthenticateEvent.bind(this)); this.socket.on('lock', this.handleLockEvent.bind(this)); this.socket.on('unlock', this.handleUnlockEvent.bind(this)); this.socket.on('getLock', this.handleGetLockEvent.bind(this)); this.socket.on( 'subscribeToObjectTypeUpdate', this.handleSubscribeToObjectTypeUpdateEvent.bind(this) ); this.socket.on( 'subscribeToObjectUpdate', this.handleSubscribeToObjectUpdateEvent.bind(this) ); this.socket.on( 'subscribeToObjectEvent', this.handleSubscribeToObjectEventEvent.bind(this) ); this.socket.on( 'unsubscribeObjectTypeUpdate', this.handleUnsubscribeToObjectTypeUpdateEvent.bind(this) ); this.socket.on( 'unsubscribeObjectUpdate', this.handleUnsubscribeToObjectUpdateEvent.bind(this) ); this.socket.on( 'unsubscribeObjectEvent', this.handleUnsubscribeObjectEventEvent.bind(this) ); this.socket.on( 'subscribeToModelStats', this.handleSubscribeToStatsEvent.bind(this) ); this.socket.on( 'unsubscribeModelStats', this.handleUnsubscribeToStatsEvent.bind(this) ); this.socket.on( 'previewTemplate', this.handlePreviewTemplateEvent.bind(this) ); this.socket.on( 'renderTemplatePDF', this.handleRenderTemplatePDFEvent.bind(this) ); this.socket.on( 'generateHostOtp', this.handleGenerateHostOtpEvent.bind(this) ); this.socket.on('objectAction', this.handleObjectActionEvent.bind(this)); this.socket.on('disconnect', this.handleDisconnect.bind(this)); } async handleAuthenticateEvent(data, callback) { const token = data.token || undefined; logger.info('Authenticating user with token...'); if (token) { const result = await this.keycloakAuth.verifyToken(token); if (result.valid == true) { logger.info('User authenticated and valid.'); this.user = result.user; this.id = this.user._id.toString(); this.authenticated = true; } else { logger.warn('User is not authenticated.'); } callback(result); } } async handleLockEvent(data) { // data: { _id: string, params?: object } if (!data || !data._id) { this.socket.emit('lock_result', { success: false, error: 'Invalid lock event data' }); return; } data = { ...data, user: this.user._id.toString() }; try { await this.lockManager.lockObject(data); } catch (err) { logger.error('Lock event error:', err); this.socket.emit('lock_result', { success: false, error: err.message }); } } async handleUnlockEvent(data) { // data: { _id: string } if (!data || !data._id) { this.socket.emit('unlock_result', { success: false, error: 'Invalid unlock event data' }); return; } data = { ...data, user: this.user._id.toString() }; try { await this.lockManager.unlockObject(data); } catch (err) { logger.error('Unlock event error:', err); this.socket.emit('unlock_result', { success: false, error: err.message }); } } async handleGetLockEvent(data, callback) { // data: { _id: string } if (!data || !data._id) { callback({ error: 'Invalid getLock event data' }); return; } try { const lockEvent = await this.lockManager.getObjectLock(data); callback(lockEvent); } catch (err) { logger.error('GetLock event error:', err); callback({ error: err.message }); } } async handleSubscribeToObjectTypeUpdateEvent(data, callback) { await this.updateManager.subscribeToObjectNew(data.objectType); await this.updateManager.subscribeToObjectDelete(data.objectType); callback({ success: true }); } async handleSubscribeToObjectUpdateEvent(data, callback) { const result = await this.updateManager.subscribeToObjectUpdate( data._id, data.objectType ); callback(result); } async handleSubscribeToObjectEventEvent(data) { await this.eventManager.subscribeToObjectEvent( data._id, data.objectType, data.eventType ); } async handleUnsubscribeToObjectTypeUpdateEvent(data) { await this.updateManager.removeObjectNewListener(data.objectType); await this.updateManager.removeObjectDeleteListener(data.objectType); } async handleUnsubscribeToObjectUpdateEvent(data) { await this.updateManager.removeObjectUpdateListener( data._id, data.objectType ); } async handleUnsubscribeObjectEventEvent(data) { await this.eventManager.removeObjectEventsListener( data._id, data.objectType, data.eventType ); } async handleSubscribeToStatsEvent(data) { await this.statsManager.subscribeToStats(data.objectType); } async handleUnsubscribeToStatsEvent(data) { await this.statsManager.removeStatsListener(data.objectType); } async handlePreviewTemplateEvent(data, callback) { const result = await this.templateManager.renderTemplate( data._id, data.content, data.testObject, data.scale ); callback(result); } async handleRenderTemplatePDFEvent(data, callback) { const result = await this.templateManager.renderPDF( data._id, data.content, data.object, 1 ); callback(result); } async handleGenerateHostOtpEvent(data, callback) { const result = await generateHostOTP(data._id); callback(result); } async handleObjectActionEvent(data, callback) { await this.actionManager.sendObjectAction( data._id, data.objectType, data.action, callback ); } async handleDisconnect() { await this.actionManager.removeAllListeners(); await this.eventManager.removeAllListeners(); await this.statsManager.removeAllListeners(); logger.info('External user disconnected:', this.socket.user?.username); } }