From e1ba1f78715710b8bd1956af940e907eeec1cf71 Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Fri, 5 Sep 2025 23:30:35 +0100 Subject: [PATCH] Implement EventManager integration and enhance socket event handling - Added EventManager to SocketHost and SocketUser for improved event handling. - Introduced new socket event handlers for editing objects, listing objects, and subscribing to object actions. - Refactored authentication logic to streamline host online status updates. - Enhanced logging and callback mechanisms for better traceability and responsiveness in socket interactions. --- src/socket/sockethost.js | 91 +++++++++++++++++++++++++++++++++------- src/socket/socketuser.js | 54 ++++++++++++++++++++++-- 2 files changed, 127 insertions(+), 18 deletions(-) diff --git a/src/socket/sockethost.js b/src/socket/sockethost.js index a3b1a37..1d2affb 100644 --- a/src/socket/sockethost.js +++ b/src/socket/sockethost.js @@ -2,11 +2,12 @@ import log4js from 'log4js'; // Load configuration import { loadConfig } from '../config.js'; import { CodeAuth, createAuthMiddleware } from '../auth/auth.js'; -import { editObject, getObject } from '../database/database.js'; +import { editObject, getObject, listObjects } from '../database/database.js'; import { hostModel } from '../database/schemas/management/host.schema.js'; import { UpdateManager } from '../updates/updatemanager.js'; import { ActionManager } from '../actions/actionmanager.js'; import { getModelByName } from '../utils.js'; +import { EventManager } from '../events/eventmanager.js'; const config = loadConfig(); @@ -23,6 +24,7 @@ export class SocketHost { this.socketManager = socketManager; this.updateManager = new UpdateManager(this); this.actionManager = new ActionManager(this); + this.eventManager = new EventManager(this); this.codeAuth = new CodeAuth(); this.setupSocketEventHandlers(); } @@ -32,6 +34,13 @@ export class SocketHost { this.socket.on('authenticate', this.handleAuthenticate.bind(this)); this.socket.on('updateHost', this.handleUpdateHost.bind(this)); this.socket.on('getObject', this.handleGetObject.bind(this)); + this.socket.on('editObject', this.handleEditObject.bind(this)); + this.socket.on('listObjects', this.handleListObjects.bind(this)); + this.socket.on( + 'subscribeToObjectActions', + this.handleSubscribeToObjectActions.bind(this) + ); + this.socket.on('objectEvent', this.handleObjectEventEvent.bind(this)); this.socket.on('disconnect', this.handleDisconnect.bind(this)); } @@ -40,6 +49,23 @@ export class SocketHost { } async handleAuthenticate(data, callback) { + const setHostOnline = async verifyResult => { + logger.info('Host authenticated and valid.'); + this.host = verifyResult.host; + this.id = this.host._id.toString(); + this.authenticated = true; + await editObject({ + model: hostModel, + id: this.host._id, + updateData: { + online: true, + state: { type: 'online' }, + connectedAt: new Date() + }, + owner: this.host, + ownerType: 'host' + }); + }; logger.trace('handleAuthenticateEvent'); const id = data.id || undefined; const authCode = data.authCode || undefined; @@ -49,17 +75,7 @@ export class SocketHost { logger.info('Authenticating host with id + authCode...'); const verifyResult = await this.codeAuth.verifyCode(id, authCode); if (verifyResult.valid == true) { - logger.info('Host authenticated and valid.'); - this.host = verifyResult.host; - this.id = this.host._id.toString(); - this.authenticated = true; - await editObject({ - model: hostModel, - id: this.host._id, - updateData: { online: true, state: { type: 'online' } }, - owner: this.host, - ownerType: 'host' - }); + await setHostOnline(verifyResult); await this.initializeHost(); } callback(verifyResult); @@ -71,8 +87,8 @@ export class SocketHost { const verifyResult = await this.codeAuth.verifyOtp(otp); if (verifyResult.valid == true) { logger.info('Host authenticated and valid.'); - this.host = verifyResult.host; - this.authenticated = true; + await setHostOnline(verifyResult); + await this.initializeHost(); } callback(verifyResult); return; @@ -91,6 +107,18 @@ export class SocketHost { }); } + async handleEditObject(data, callback) { + const object = await editObject({ + model: getModelByName(data.objectType), + id: data._id, + updateData: data.updateData, + populate: data.populate, + owner: this.host, + ownerType: 'host' + }); + callback(object); + } + async handleGetObject(data, callback) { const object = await getObject({ model: getModelByName(data.objectType), @@ -101,12 +129,45 @@ export class SocketHost { callback(object); } + async handleListObjects(data, callback) { + const object = await listObjects({ + model: getModelByName(data.objectType), + id: data._id, + cached: data?.cached, + populate: data?.populate, + filter: data?.filter, + project: data?.project, + sort: data?.sort, + order: data?.order + }); + callback(object); + } + + async handleObjectEventEvent(data) { + await this.eventManager.sendObjectEvent( + data._id, + data.objectType, + data.event + ); + } + + async handleSubscribeToObjectActions(data) { + await this.actionManager.subscribeToObjectActions( + data._id, + data.objectType + ); + } + async handleDisconnect() { if (this.authenticated) { await editObject({ model: hostModel, id: this.host._id, - updateData: { online: false, state: { type: 'offline' } }, + updateData: { + online: false, + state: { type: 'offline' }, + connectedAt: null + }, owner: this.host, ownerType: 'host' }); diff --git a/src/socket/socketuser.js b/src/socket/socketuser.js index 0187882..c41ee5b 100644 --- a/src/socket/socketuser.js +++ b/src/socket/socketuser.js @@ -6,6 +6,7 @@ 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'; const config = loadConfig(); @@ -23,6 +24,7 @@ export class SocketUser { this.lockManager = new LockManager(this); this.updateManager = new UpdateManager(this); this.actionManager = new ActionManager(this); + this.eventManager = new EventManager(this); this.templateManager = socketManager.templateManager; this.keycloakAuth = new KeycloakAuth(); this.setupSocketEventHandlers(); @@ -42,6 +44,22 @@ export class SocketUser { '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( 'previewTemplate', this.handlePreviewTemplateEvent.bind(this) @@ -60,6 +78,7 @@ export class SocketUser { 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; @@ -126,18 +145,47 @@ export class SocketUser { } async handleSubscribeToObjectTypeUpdateEvent(data, callback) { - const result = this.updateManager.subscribeToObjectNew(data.objectType); - callback(result); + await this.updateManager.subscribeToObjectNew(data.objectType); + await this.updateManager.subscribeToObjectDelete(data.objectType); + callback({ success: true }); } async handleSubscribeToObjectUpdateEvent(data, callback) { - const result = this.updateManager.subscribeToObjectUpdate( + 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 handlePreviewTemplateEvent(data, callback) { const result = await this.templateManager.renderTemplate( data._id,