lib_factory_model_sanitize-body.js
/**
* Sanitize the payload body based on the model's properties and rules.
* @method
* @memberof DoboModel
* @async
* @param {Object} [options={}] - Options object
* @param {Object} [options.body={}] - Body object to sanitize
* @param {boolean} [options.partial=false] - If `true`, only the fields present in the body will be sanitized
* @param {boolean} [options.strict=false] - If `true`, only the fields defined in the model's properties will be included in the sanitized body
* @param {Array} [options.extFields=[]] - Additional fields to include in the sanitized body
* @param {boolean} [options.truncateString=false] - If `true`, string fields will be truncated to their maximum length defined in the model's properties
* @param {string} [options.action] - The action being performed (e.g., 'createRecord', 'updateRecord', etc.)
* @param {boolean} [options.allProps=false] - If `true`, all properties including virtual ones will be considered for sanitization
* @returns {Object} Returns sanitized body object
*/
async function sanitizeBody (options = {}) {
const { body = {}, partial, strict, extFields = [], truncateString, action, allProps } = options
const { isSet } = this.app.lib.aneka
const { sanitizeByType } = this.app.dobo
const { omit, has } = this.app.lib._
const result = {}
const sanitize = (name, type) => {
const opts = { strict, action, model: this.name, outputFormat: 'native' }
result[name] = sanitizeByType(result[name], type, opts)
if (['updateRecord', 'upsertRecord'].includes(action) && type === 'string' && result[name] === '') result[name] = null
}
const omitted = []
const details = []
const props = allProps ? this.properties : this.getNonVirtualProperties()
const properties = [...props, ...extFields]
for (const prop of properties) {
try {
if (partial && !has(body, prop.name)) {
// if (prop.type === 'array') result[prop.name] = null
continue
}
result[prop.name] = body[prop.name]
if (prop.type === 'array' && isSet(result[prop.name]) && !Array.isArray(result[prop.name])) result[prop.name] = [result[prop.name]]
if (isSet(result[prop.name])) sanitize(prop.name, prop.type)
if (result[prop.name] === null) continue
if (truncateString && isSet(result[prop.name]) && ['string', 'text'].includes(prop.type)) result[prop.name] = result[prop.name].slice(0, prop.maxLength)
if (prop.name.endsWith('Id') && isSet(result[prop.name]) && prop.type === 'string' && ['smallint', 'integer'].includes(this.adapter.idField.type)) result[prop.name] = result[prop.name] + ''
if (result[prop.name] === undefined) omitted.push(prop.name)
} catch (err) {
details.push({ field: prop.name, error: err.message, value: body[prop.name], ext: { type: prop.type } })
}
}
if (details.length > 0) {
const payload = { details, statusCode: 422, code: 'BODY_SANITIZATION', model: this.name }
throw this.plugin.error('sanitizeBodyError', payload)
}
return omit(result, omitted)
}
export default sanitizeBody