method_sanitize_body.js

/**
 * Sanitize payload body against schema
 *
 * @method
 * @memberof Dobo
 * @async
 * @param {Object} [options={}]
 * @param {Object} [options.body={}]
 * @param {Object} [options.schema={}]
 * @param {boolean} [options.partial=false]
 * @param {boolean} [options.strict=false]
 * @param {Array} [options.extFields=[]]
 * @returns {Object}
 */

async function sanitizeBody ({ body = {}, schema = {}, partial, strict, extFields = [] }) {
  const { isSet } = this.app.lib.aneka
  const { dayjs } = this.app.lib
  const { callHandler } = this.app.bajo
  const { has, isString, isNumber, concat, isNaN } = this.app.lib._
  const result = {}
  for (const p of concat(schema.properties, extFields)) {
    if (partial && !has(body, p.name)) continue
    if (['object', 'array'].includes(p.type)) {
      if (isString(body[p.name])) {
        try {
          result[p.name] = JSON.parse(body[p.name])
        } catch (err) {
          result[p.name] = null
        }
      } else {
        try {
          result[p.name] = JSON.parse(JSON.stringify(body[p.name]))
        } catch (err) {}
      }
    } else result[p.name] = body[p.name]
    if (isSet(body[p.name])) {
      if (p.type === 'boolean') result[p.name] = result[p.name] === null ? null : (['true', true].includes(result[p.name]))
      if (['float', 'double'].includes(p.type)) {
        if (isNumber(body[p.name])) result[p.name] = body[p.name]
        else if (strict) {
          result[p.name] = Number(body[p.name])
        } else {
          result[p.name] = parseFloat(body[p.name]) || null
        }
      }
      if (['integer', 'smallint'].includes(p.type)) {
        if (isNumber(body[p.name])) result[p.name] = body[p.name]
        else if (strict) {
          result[p.name] = Number(body[p.name])
        } else {
          result[p.name] = parseInt(body[p.name]) || null
        }
      }
      if (p.type === 'timestamp') {
        if (!isNumber(body[p.name])) result[p.name] = -1
        else {
          const dt = dayjs.unix(body[p.name])
          result[p.name] = dt.isValid() ? dt.unix() : -1
        }
      } else {
        for (const t of ['datetime', 'date|YYYY-MM-DD', 'time|HH:mm:ss']) {
          const [type, input] = t.split('|')
          if (p.type === type) result[p.name] = this.sanitizeDate(body[p.name], { input })
        }
      }
      if (['string', 'text'].includes(p.type)) result[p.name] = body[p.name] + ''
    } else {
      if (isSet(p.default)) {
        result[p.name] = p.default
        if (isString(p.default) && p.default.startsWith('handler:')) {
          const [, ...args] = p.default.split(':')
          if (args.length > 0) result[p.name] = await callHandler(args.join(':'))
        } else {
          if (['float', 'double'].includes(p.type)) result[p.name] = parseFloat(result[p.name])
          if (['integer', 'smallint'].includes(p.type)) result[p.name] = parseInt(result[p.name])
          if (isNaN(result[p.name])) result[p.name] = null
        }
      }
    }
  }
  return result
}

export default sanitizeBody