farmcontrol-ws/src/socket/socketuser.js
2025-12-13 21:03:55 +00:00

252 lines
7.2 KiB
JavaScript

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);
}
}