import type { IAuditServerAppActor, IAuditServerSystemActor, IAuditServerUserActor, ISetting, SettingValue, } from '@rocket.chat/core-typings'; import { ServerEvents } from '@rocket.chat/models'; import { settings } from '../cached'; const shouldMaskSettingInAudit = (settingId: ISetting['_id']): boolean => { const setting = settings.getSetting(settingId); return Boolean(setting && (setting.type === 'password' || (setting.type === 'string' && setting.secret === true))); }; const maskIfNeeded = (settingId: ISetting['_id'], value: SettingValue): SettingValue => { if (!shouldMaskSettingInAudit(settingId)) { return value; } if (value === undefined || value === null || value === '') { return value; } const valueString = String(value); const valueLength = valueString.length; let maskedValue: string; if (valueLength <= 8) { maskedValue = '*'.repeat(valueLength); } else { maskedValue = valueString.substring(0, 3) + '*'.repeat(valueLength - 3); } return maskedValue; }; export const resetAuditedSettingByUser = (actor: Omit) => any>(fn: F, key: ISetting['_id']): ReturnType => { const { value, packageValue } = settings.getSetting(key) ?? {}; void ServerEvents.createAuditServerEvent( 'settings.changed', { id: key, previous: maskIfNeeded(key, value), current: maskIfNeeded(key, packageValue), }, { type: 'user', ...actor, }, ); return fn(key); }; export const updateAuditedByUser = (actor: Omit) => any>( fn: F, ...args: Parameters ): ReturnType => { const [key, value, ...rest] = args; const setting = settings.getSetting(key); const previous = setting?.value; void ServerEvents.createAuditServerEvent( 'settings.changed', { id: key, previous: maskIfNeeded(key, previous), current: maskIfNeeded(key, value), }, { type: 'user', ...actor, }, ); return fn(key, value, ...rest); }; export const updateAuditedBySystem = (actor: Omit) => any>( fn: F, ...args: Parameters ): ReturnType => { const [key, value, ...rest] = args; const setting = settings.getSetting(key); const previous = setting?.value; void ServerEvents.createAuditServerEvent( 'settings.changed', { id: key, previous: maskIfNeeded(key, previous), current: maskIfNeeded(key, value), }, { type: 'system', ...actor, }, ); return fn(key, value, ...rest); }; export const updateAuditedByApp = any>( actor: Omit, ) => (fn: F, ...args: Parameters): ReturnType => { const [key, value, ...rest] = args; const setting = settings.getSetting(key); const previous = setting?.value; void ServerEvents.createAuditServerEvent( 'settings.changed', { id: key, previous: maskIfNeeded(key, previous), current: maskIfNeeded(key, value), }, { type: 'app', ...actor, }, ); return fn(key, value, ...rest); };