GithubHelp home page GithubHelp logo

Error with nested properties about bodymen HOT 14 OPEN

diegohaz avatar diegohaz commented on May 26, 2024
Error with nested properties

from bodymen.

Comments (14)

chemitaxis avatar chemitaxis commented on May 26, 2024 4

Hi @khelkun, my workaround is something like this:

const contextSchema = new Schema({
  user: {
    type: Schema.ObjectId,
    ref: 'User',
    required: true
  },
  rootview: {
    type: String
  },
  directoryview: {
    type: String
  },
  mimetypes: { type: Object }
}, {
  timestamps: true
});

I have changed mimetypes to Object, you can validate after, what you want.

Thanks!

from bodymen.

chemitaxis avatar chemitaxis commented on May 26, 2024

Hi @diegohaz , the problem is in the validator method, BUT the problem is not in Bodymen, is your other module rich-param, it can't work fine with objects.

If I change in the validator method this:

/**
   * Validate values of the schema params.
   * @param {Object} [values] - Object with {param: value} pairs to validate.
   * @param {Function} [next] - Callback to be called with error
   * @return {boolean} Result of the validation.
   */
  validate (values = {}, next = error => !error) {
    let error
    if (_.isFunction(values)) {
      next = values
      values = {}
    }

    _.forIn(this.params, param => {
      const value = values[this._getBodyParamName(param.name)]
     
      if (!_.isNil(value)) {
        // THIS LINE ADDED TO CHECK IF OBJECT
        if (typeof value === 'object') {
          param._value = value
        } else {
          param.value(value)
        }
      }
    })

    for (let i in this.params) {
      if (error) break
      const param = this.params[i]
      param.validate(err => {
        error = err
      })
    }

    return next(error)
  }

What is the best way to solve this problem? Thanks

from bodymen.

chemitaxis avatar chemitaxis commented on May 26, 2024

But... with this, the nested property is not checked... :(

from bodymen.

chemitaxis avatar chemitaxis commented on May 26, 2024

Ok, more information...

If I configure my schema like this in the body:

{
  'Name': String,
  'Address' : {
          type: Object 
   }
}

It works... but the validation of Address properties is not triggered... thanks.

from bodymen.

diegohaz avatar diegohaz commented on May 26, 2024

@chemitaxis Thank you for reporting. This is a known problem, but not very easy to fix.

FYI, I'm working on a new library to replace querymen, bodymen and rich-param. That solves issues like diegohaz/querymen#30 and this one.

https://github.com/diegohaz/schm

Currently, it lacks validation (diegohaz/schm#1 - almost done on dev branch), express and mongoose support, but these probably will be implemented in the next few weeks. Any help is welcome.

from bodymen.

chemitaxis avatar chemitaxis commented on May 26, 2024

Hi @diegohaz, perfect and thanks. I will check this new repo, and I will try to contribute. My workaround is validate with express-validator. One question, I did not found problems with the issue that you mentioned, diegohaz/querymen#30, but can you please confirm me if I need to be worried about it? ;)

from bodymen.

chemitaxis avatar chemitaxis commented on May 26, 2024

I have check the code, it would be easier to contribute if you document a litte the code ;) For example, how walk method works in utils? Thank you so much!

from bodymen.

khelkun avatar khelkun commented on May 26, 2024

Hi I'm using the @diegohaz's rest project generator.
I think my problem is the similar to @chemitaxis's problem.
I have this Schema :

const contextSchema = new Schema({
  user: {
    type: Schema.ObjectId,
    ref: 'User',
    required: true
  },
  rootview: {
    type: String
  },
  directoryview: {
    type: String
  },
  mimetypes: [ { mime: String, viewer: String } ]
}, {
  timestamps: true
});

The index.test.js of the api is sends this:

test('POST /contexts 201 (user)', async () => {
  const { status, body } = await request(app())
    .post('/')
    .send({
      access_token: userSession,
      rootview: 'UvCardRootView',
      directoryview: 'UvDiffusionDirectoryView',
      mimetypes: [
        { mime: 'image/jpeg', viewer: 'UvDiffusionImageViewer' },
        { mime: 'application/pdf', viewer: 'UvEmbeddedImagePdfViewer' },
        { mime: 'video/mp4', viewer: 'UvBrowserVideoViewer' }
      ]
    });

On the api side it seems that bodymen cannot parse the mimetypes field.
Indeed the create method of my api controller receives this body object:

body = Object
   directoryview = "UvDiffusionDirectoryView"
   mimetypes = "[object Object],[object Object],[object Object]"
   rootview = "UvCardRootView"

So body.mimetypes is not an array but a toString of it. I debugged in bodymen and indeed the following line in the middleware function doesn't give me the source req.body.mimetypes array but an "[object Object],[object Object],[object Object]":
req.bodymen = { body: _schema.parse(), schema: _schema };

I'm really new to all this validation, mongoose, schema, nested schema ... I did read Mongoose doc, took the time to understand what I could in @diegohaz's work but I don't know how to workaround this.
Can you help me ? How I could at least disable the bodymen validation for this api? And so forth directly send the json parsed req.body to the create method of my api controller?
I mean what I should doin from the context/index.js of my api? here:

import { Router } from 'express';
import { middleware as query } from 'querymen';
import { middleware as body } from 'bodymen';
import { token } from '../../services/passport';
import { create, index, show, update, destroy } from './controller';
import { schema } from './model';
export Context, { schema } from './model';

const router = new Router();
const { rootview, directoryview, mimetypes } = schema.tree;

router.post('/',
  token({ required: true }),
  body({ rootview, directoryview, mimetypes }),
  create);

from bodymen.

khelkun avatar khelkun commented on May 26, 2024

@chemitaxis thanks it actually works!
it also works with this schema:

const contextSchema = new Schema({
  user: {
    type: Schema.ObjectId,
    ref: 'User',
    required: true
  },
  rootview: {
    type: String
  },
  directoryview: {
    type: String
  },
  mimetypes: [ { type: Object } ]
}, {
  timestamps: true
});

Which is probably a bit more accurate since mimetypes field is supposed to be an Array of Objects.
Still I wish I could have specified in the schema that each Object in the mimetypes Array has 2 String fields: mime and viewer. But apparently I'll not be able to validate this.

from bodymen.

khelkun avatar khelkun commented on May 26, 2024

Also note that bodymen succeeds to validate a body containing [ { mime: "test", viewer: "test"} ] for a schema definition like this:
mimetypes: { type: Object, required:true }

But bodymen fails to validate the same body with a schema definition like this:
mimetypes: [ { type: Object, required:true } ]

from bodymen.

chemitaxis avatar chemitaxis commented on May 26, 2024

Interesting... you can validate an array ob objects?

from bodymen.

khelkun avatar khelkun commented on May 26, 2024

My bad it's not bodymen issue. The validation error comes from mongoose:

Failed: Context validation failed: mimetypes: Cast to Array failed for value "[ { mime: 'image/jpeg', viewer: 'UvMessidorImageViewer' },
  { mime: 'application/pdf', viewer: 'UvEmbeddedImagePdfViewer' } ]" at path "mimetypes"
ValidationError: Context validation failed: mimetypes: Cast to Array failed for value "[ { mime: 'image/jpeg', viewer: 'UvMessidorImageViewer' },
  { mime: 'application/pdf', viewer: 'UvEmbeddedImagePdfViewer' } ]" at path "mimetypes"
    at MongooseError.ValidationError (/home/me/myprojectnode_modules/mongoose/lib/error/validation.js:28:11)
    at model.Object.<anonymous>.Document.invalidate (/home/me/myprojectnode_modules/mongoose/lib/document.js:1612:32)
    at model.Object.<anonymous>.Document.set (/home/me/myprojectnode_modules/mongoose/lib/document.js:761:10)
    at model._handleIndex (/home/me/myprojectnode_modules/mongoose/lib/document.js:594:14)
    at model.Object.<anonymous>.Document.set (/home/me/myprojectnode_modules/mongoose/lib/document.js:554:24)
    at model.Document (/home/me/myprojectnode_modules/mongoose/lib/document.js:73:12)
    at model.Model (/home/me/myprojectnode_modules/mongoose/lib/model.js:47:12)
    at new model (/home/me/myprojectnode_modules/mongoose/lib/model.js:3688:13)
    at /home/me/myprojectnode_modules/mongoose/lib/model.js:1942:51
    at /home/me/myprojectnode_modules/async/internal/parallel.js:27:9
    at eachOfArrayLike (/home/me/myprojectnode_modules/async/eachOf.js:57:9)
    at Object.<anonymous>.exports.default (/home/me/myprojectnode_modules/async/eachOf.js:9:5)
    at _parallel (/home/me/myprojectnode_modules/async/internal/parallel.js:26:5)
    at parallelLimit (/home/me/myprojectnode_modules/async/parallel.js:85:26)
    at /home/me/myprojectnode_modules/mongoose/lib/model.js:1963:5
    at Promise._execute (/home/me/myprojectnode_modules/bluebird/js/release/debuggability.js:300:9)
    at Promise._resolveFromExecutor (/home/me/myprojectnode_modules/bluebird/js/release/promise.js:483:18)
    at new Promise (/home/me/myprojectnode_modules/bluebird/js/release/promise.js:79:10)
    at Function.create (/home/me/myprojectnode_modules/mongoose/lib/model.js:1926:17)
    at _callee$ (/home/me/myprojectsrc/api/context/index.test.js:16:49)
    at tryCatch (/home/me/myprojectnode_modules/regenerator-runtime/runtime.js:65:40)
    at GeneratorFunctionPrototype.invoke [as _invoke] (/home/me/myprojectnode_modules/regenerator-runtime/runtime.js:299:22)

So I guess mimetypes: [ { type: Object, required:true } ] is not a valid schema definition... To be honnest I barely know what I'm doing

from bodymen.

chemitaxis avatar chemitaxis commented on May 26, 2024

from bodymen.

khelkun avatar khelkun commented on May 26, 2024

Sorry I deleted the message cause the change I was talking about actually breaks bodymen.
It works for my schema but the tests fails on the schemas of the others api (auth, password, users).

from bodymen.

Related Issues (9)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.