import { userSettingsModel } from '../database/schemas/misc/usersettings.schema.js'; const SETTINGS_CATEGORIES = [ 'viewMode', 'filterSidebarVisibility', 'sortSidebarVisibility', 'columnVisibility', 'collapseState' ]; const createEmptySettings = () => ({ viewMode: {}, filterSidebarVisibility: {}, sortSidebarVisibility: {}, columnVisibility: {}, collapseState: {} }); const normalizeCategory = category => category && typeof category === 'object' && !Array.isArray(category) ? category : {}; const normalizeSettings = (defaults = {}) => ({ viewMode: normalizeCategory(defaults?.viewMode), filterSidebarVisibility: normalizeCategory(defaults?.filterSidebarVisibility), sortSidebarVisibility: normalizeCategory(defaults?.sortSidebarVisibility), columnVisibility: normalizeCategory(defaults?.columnVisibility), collapseState: normalizeCategory(defaults?.collapseState) }); const isSafeSettingsKey = key => typeof key === 'string' && key.length > 0 && key.length <= 128 && !key.includes('.') && !key.includes('$') && !key.includes('\0'); export class UserSettingsManager { constructor(socketClient) { this.socketClient = socketClient; } getUserId() { const userId = this.socketClient.user?._id; if (!this.socketClient.authenticated || !userId) { throw new Error('User is not authenticated'); } return userId; } async getUserSettings() { const userId = this.getUserId(); const userSettings = await userSettingsModel .findOne({ user: userId }) .select('defaults') .lean(); return normalizeSettings(userSettings?.defaults); } async updateUserSettings({ category, key, value } = {}) { const userId = this.getUserId(); if (!SETTINGS_CATEGORIES.includes(category)) { throw new Error('Invalid user settings category'); } if (!isSafeSettingsKey(key)) { throw new Error('Invalid user settings key'); } if (value === undefined) { throw new Error('User settings value is required'); } const update = { $set: { [`defaults.${category}.${key}`]: value, updatedAt: new Date() }, $setOnInsert: { user: userId, createdAt: new Date() } }; let userSettings; try { userSettings = await userSettingsModel .findOneAndUpdate({ user: userId }, update, { new: true, upsert: true, setDefaultsOnInsert: true }) .select('defaults') .lean(); } catch (error) { if (error?.code !== 11000) { throw error; } userSettings = await userSettingsModel .findOneAndUpdate( { user: userId }, { $set: update.$set }, { new: true } ) .select('defaults') .lean(); } return normalizeSettings(userSettings?.defaults); } } export { SETTINGS_CATEGORIES, createEmptySettings, isSafeSettingsKey };