arb / celebrate

A joi validation middleware for Express.
MIT License
1.33k stars 66 forks source link

Support Context and Refs #100

Closed arb closed 5 years ago

arb commented 5 years ago

Let users access the req object in validation schema.

https://github.com/hapijs/joi/blob/master/API.md#validatevalue-schema-options-callback

context

fahrenq commented 5 years ago

Hey @arb!

First of all - thank you for all the hard work on this package, it's awesome!

I just wanted to create an issue here on Github, but I found that this ticket is very close to my question, probably what I'm about to ask will be implemented in 9.1.0 version, but I'll ask anyway:

Is there a way to validate things across 2 "sources", i.e. body and params?

For example: I need to validate weekday field in body and allow it only in case if kind is weekly. If kind would be in body, I would do something like this: (maybe this code wouldn't work, it doesn't matter). But how do I do the same thing but my kind is actually a part of a path, i.e. it is in params?

Thanks!

const requestValidation = celebrate({
  body: Joi.object().keys({
    kind: Joi.string().valid(['daily', 'weekly', 'monthly']),
    weekday: Joi.when('kind', {
      is: 'weekly',
      then: Joi.number()
        .min(0)
        .max(6),
      otherwise: Joi.forbidden(),
    }),
  }),
});
arb commented 5 years ago

@fahrenq thanks for the kind words!

You're right, you'd do this with ref. I'm planning on adding this in the next minor release. Right now, you don't have access to the entire req object when validating schemas so you can't reference other values inside req. Once I add this feature, you'll be able to do what you're asking.

zerefel commented 5 years ago

I also hit a wall looking to validate params and body at the same time. My use case is the following:

If value is passed in the body of a request take it. As a fallback, the value is taken from the headers, if set.

I thought something like this might work (the use of xor may be wrong altogether, first time writing Joi schemas):

// pseudo code
const validator = Joi.object().keys({
    body: Joi.object().keys({
        value: Joi.string().required()
    }),
    headers: Joi.object().keys({
        value: Joi.string().required()
    })
}).xor('body', 'headers');

celebrate(validator);

However, this fails celebrate's validation for a schema, it doesn't expect a Joi schema, it expects an object. Do you think it's possible to determine whether the provided object is a Joi schema, and if it is, tap into its internals and validate those to make sure one of body, params, query, headers, cookies, signedCooies exists?

arb commented 5 years ago

@zerefel let's get refs working first and then see if you can solve your problem that way. celebrates API is strongly influenced (aka copied) from how you validate parts of the request in hapi so I'd like to keep the API the same if possible.

arb commented 5 years ago

Hey @zerefel; version 9.1.0 was just pushed to npm; give it a spin and let me know if it gets you where you need to go!