peertube-plugin-livechat/server/lib/configuration/channel/sanitize.ts

88 lines
2.5 KiB
TypeScript
Raw Normal View History

2023-08-09 14:16:02 +00:00
import type { RegisterServerOptions } from '@peertube/peertube-types'
2023-09-18 10:23:35 +00:00
import type { ChannelConfigurationOptions } from '../../../../shared/lib/types'
2023-08-09 14:16:02 +00:00
/**
* Sanitize data so that they can safely be used/stored for channel configuration configuration.
2023-08-09 14:16:02 +00:00
* Throw an error if the format is obviously wrong.
* Cleans data (removing empty values, ...)
* @param options Peertube server options
* @param _channelInfos Channel infos
* @param data Input data
*/
async function sanitizeChannelConfigurationOptions (
2023-08-09 14:16:02 +00:00
_options: RegisterServerOptions,
2023-09-18 10:23:35 +00:00
_channelId: number | string,
2023-08-09 14:16:02 +00:00
data: any
): Promise<ChannelConfigurationOptions> {
2023-08-09 14:16:02 +00:00
if (typeof data !== 'object') {
throw new Error('Invalid data type')
}
2023-09-19 16:56:39 +00:00
const result: ChannelConfigurationOptions = {
bot: _readBoolean(data, 'bot'),
botNickname: _readSimpleInput(data, 'botNickname'),
bannedJIDs: await _readRegExpArray(data, 'bannedJIDs'),
forbiddenWords: await _readRegExpArray(data, 'forbiddenWords')
}
return result
}
function _readBoolean (data: any, f: string): boolean {
if (!(f in data)) {
return false
}
if (typeof data[f] !== 'boolean') {
throw new Error('Invalid data type for field ' + f)
}
return data[f]
}
function _readSimpleInput (data: any, f: string): string {
if (!(f in data)) {
return ''
}
if (typeof data[f] !== 'string') {
throw new Error('Invalid data type for field ' + f)
}
// Replacing all invalid characters, no need to throw an error..
return (data[f] as string).replace(/[^\p{L}\p{N}\p{Z}_-]$/gu, '')
}
async function _readRegExpArray (data: any, f: string): Promise<string[]> {
// Note: this function can instanciate a lot of RegExp.
// To avoid freezing the server, we make it async, and will validate each regexp in a separate tick.
if (!(f in data)) {
return []
2023-08-09 14:16:02 +00:00
}
2023-09-19 16:56:39 +00:00
if (!Array.isArray(data[f])) {
throw new Error('Invalid data type for field ' + f)
}
const result: string[] = []
for (const v of data[f]) {
if (typeof v !== 'string') {
throw new Error('Invalid data type in a value of field ' + f)
2023-08-09 14:16:02 +00:00
}
2023-09-19 16:56:39 +00:00
if (v === '' || /^\s+$/.test(v)) {
// ignore empty values
continue
}
// value must be a valid regexp
try {
async function _validate (): Promise<void> {
2023-08-09 14:16:02 +00:00
// eslint-disable-next-line no-new
new RegExp(v)
}
2023-09-19 16:56:39 +00:00
await _validate()
} catch (_err) {
throw new Error('Invalid value in field ' + f)
2023-08-09 14:16:02 +00:00
}
2023-09-19 16:56:39 +00:00
result.push(v)
2023-08-09 14:16:02 +00:00
}
return result
}
export {
sanitizeChannelConfigurationOptions
2023-08-09 14:16:02 +00:00
}