From b0aaa246603df147f2a81b91153c9ed1144e599d Mon Sep 17 00:00:00 2001 From: advplyr Date: Tue, 12 May 2026 16:57:28 -0500 Subject: [PATCH] Update socket events to check client is admin & validate log level --- server/SocketAuthority.js | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/server/SocketAuthority.js b/server/SocketAuthority.js index ad55f6605..a54231d75 100644 --- a/server/SocketAuthority.js +++ b/server/SocketAuthority.js @@ -3,6 +3,7 @@ const Logger = require('./Logger') const Database = require('./Database') const TokenManager = require('./auth/TokenManager') const CoverSearchManager = require('./managers/CoverSearchManager') +const { LogLevel } = require('./utils/constants') /** * @typedef SocketClient @@ -85,6 +86,14 @@ class SocketAuthority { } } + requireAdminSocket(socket, eventName) { + const client = this.clients[socket.id] + if (client?.user?.isAdminOrUp) return true + + Logger.warn(`[SocketAuthority] Unauthorized ${eventName} socket event from socket ${socket.id}`) + return false + } + /** * Emits event with library item to all clients that can access the library item * Note: Emits toOldJSONExpanded() @@ -179,14 +188,25 @@ class SocketAuthority { socket.on('auth', (token) => this.authenticateSocket(socket, token)) // Scanning - socket.on('cancel_scan', (libraryId) => this.cancelScan(libraryId)) + socket.on('cancel_scan', (libraryId) => { + if (!this.requireAdminSocket(socket, 'cancel_scan')) return + this.cancelScan(libraryId) + }) // Cover search streaming socket.on('search_covers', (payload) => this.handleCoverSearch(socket, payload)) socket.on('cancel_cover_search', (requestId) => this.handleCancelCoverSearch(socket, requestId)) // Logs - socket.on('set_log_listener', (level) => Logger.addSocketListener(socket, level)) + socket.on('set_log_listener', (level) => { + if (!this.requireAdminSocket(socket, 'set_log_listener')) return + + if (!Number.isInteger(level) || !Object.values(LogLevel).includes(level)) { + Logger.warn(`[SocketAuthority] Invalid set_log_listener level from socket ${socket.id}`) + return + } + Logger.addSocketListener(socket, level) + }) socket.on('remove_log_listener', () => Logger.removeSocketListener(socket.id)) // Sent automatically from socket.io clients