poppinss / indicative

Indicative is a simple yet powerful data validator for Node.js and browsers. It makes it so simple to write async validations on nested set of data.
https://indicative.adonisjs.com/
MIT License
417 stars 52 forks source link

Sanitise causing problems when run on partial data #150

Closed thetutlage closed 6 years ago

thetutlage commented 6 years ago

From @webdevian on April 28, 2017 12:36

Let's say I have a schema with 3 fields:

static get sanitisationRules () {
    return {
      headline: 'escape',
      description: 'escape',
      instructions: 'escape'
  }
}

If I want to only sanitise 2 fields (because they're the only one the user has posted), I pass them like this:

Validator.sanitize({
  description: 'Some description',
  instructions: 'Some instructions'
}, Model.sanitisationRules)

it returns:

{
  headline: undefined
  description: 'Some description',
  instructions: 'Some instructions'
}

When combined with Lucid's fill method it overwrites attributes as undefined which causes me problems when calling toJSON on it later (for passing to a view etc). Luckily it doesn't overwrite it as undefined on save.

Is there a way to make sanitisation rules only return a value when the field is present? If not, is there a way to make Lucid fill ignore fields that are undefined?

If I can't do that either, what is the best approach to sanitising then updating partial model data? The easiest I can think of is merging the sanitised data with the user-input data so that the undefined fields aren't there at all, then passing it to lucid fill.

Copied from original issue: adonisjs/adonis-validation-provider#18

thetutlage commented 6 years ago

From @webdevian on May 12, 2017 12:32

In the end I went with this solution to remove undefined and NaN values from an object before using it to fill a model instance

  /**
   * Sanitize model instance removing undefined values
   * @param  {Object} obj   Object to be sanitised
   * @param  {Object} rules Object to be sanitised
   * @return {Object}       sanitised object
   */
  cleanSanitize (obj, rules) {
    return this.cleanObject(Validator.sanitize(obj, rules))
  }

  /**
   * Remove undefined keys from an object. Useful for preparing
   * sanitized fields before filling the model
   * @param  {Object} obj Object to be cleaned
   * @return {Object}     cleaned object
   */
  cleanObject (obj) {
    Object.keys(obj).forEach(key => (typeof obj[key] === 'undefined' || obj[key] !== obj[key]) && delete obj[key])
    return obj
  }
thetutlage commented 6 years ago

Sorry for the late response, not sure how this issue got skipped.

Yeah sanitize method should handle this. I will fix it