arb / celebrate

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

Assertion error on validating an uri #222

Closed gpmarchi closed 3 years ago

gpmarchi commented 3 years ago

My joi schema looks like this:

[ link: Joi.string().uri({ domain: { tlds: { allow: true, }, }, }).required() ]

Here is an example value that is not working as expected:

[http:/instagram.com or http:instagram.com]

The issue I am having with celebrate is:

Hi, so the issue I've been having with this is that whenever I try to pass on an invalid uri like the ones from the examples (missing a forward slash or both) I get an assertion error like the one below:

[ AssertionError [ERR_ASSERTION]: value must be a joi validation error at Map.set (/Users/dev/Documents/Projects/backend/node_modules/celebrate/lib/CelebrateError.js:11:12) at /Users/dev/Documents/Projects/backend/node_modules/celebrate/lib/celebrate.js:96:19 at processTicksAndRejections (internal/process/task_queues.js:93:5) { generatedMessage: false, code: 'ERR_ASSERTION', actual: false, expected: true, operator: '==' } ]

I actually don't know if I'm using this the right way, but it seems strange to me that this example is not being identified as an invalid uri and instead what I get back is an assertion error. Please help me to figure this out, thanks.

arb commented 3 years ago

Can you show how you are calling celebrate?

gpmarchi commented 3 years ago

Basically I'm calling it as a middleware in express (profileCreateValidator):

[ profilesRouter.post('/', profileCreateValidator, profilesController.create); ]

This link validation is part of a larger validation of the body segment of the request.

If you need me to post the entire validation please let me know.

arb commented 3 years ago

That's not enough code. I need to see how you're using celebrate.

gpmarchi commented 3 years ago

Okay, here you go:

import { celebrate, Joi, Segments } from 'celebrate';

const pattern =
  '^[^\\s\\.\\,\\;\\:\\?\\~\\^\\´\\`\\[\\]\\{\\}\\=\\+\\-\\_\\<\\>\\|\\\\\'\\"\\#\\$\\%\\¨\\*\\(\\)\\/]+$';

export default celebrate({
  [Segments.BODY]: Joi.object().keys({
    public_key: Joi.string().required(),
    owner_public_key: Joi.string(),
    first_name: Joi.string().when('owner_public_key', {
      is: Joi.exist(),
      then: Joi.forbidden(),
      otherwise: Joi.string().required(),
    }),
    last_name: Joi.string().when('owner_public_key', {
      is: Joi.exist(),
      then: Joi.forbidden(),
      otherwise: Joi.string().required(),
    }),
    business_name: Joi.string().when('owner_public_key', {
      not: undefined,
      then: Joi.string().required().regex(new RegExp(pattern)).messages({
        'string.pattern.base':
          'Business name should not contain spaces or extensions.',
      }),
      otherwise: Joi.forbidden(),
    }),
    email: Joi.string().email().required(),
    headline: Joi.string().required().max(55),
    social_networks: Joi.array()
      .items(
        Joi.object()
          .required()
          .keys({
            slug: Joi.string().required(),
            link: Joi.string()
              .uri({
                domain: {
                  tlds: {
                    allow: true,
                  },
                },
              })
              .required(),
          }),
      )
      .min(1)
      .required(),
    payment: Joi.object().keys({
      receiving_address: Joi.string().required(),
      transaction_number: Joi.string().required(),
      value: Joi.number().required(),
    }),
  }),
});
arb commented 3 years ago

Can you also provide a request body that doesn't work? The one that causes the initial error you are asking about. I'm trying to repo locally.

arb commented 3 years ago

Ok so I did some digging. celebrate is eating the real error (which is probably a bug on my side).

I get

Invalid input: domain must be a string
    at Object.exports.analyze (/Users/_/Development/node/celebrate/node_modules/@hapi/address/lib/domain.js:21:15)
    at Object.exports.isValid (/Users/_/Development/node/celebrate/node_modules/@hapi/address/lib/domain.js:101:21)

from joi. Which makes me think joi doesn't like your schema as expressed. So that's the error that is generated when we try to validate, and since it's not a joi error, it's getting rejected by CelebrateError.

gpmarchi commented 3 years ago

Ok, this is an example request body that gives me that error:

{
    "public_key": "BC1YLh5pKXs8NqaUtN8Gzi3rfoAgG2VWio2NER7baDkG8T2x7wRnSwa",
    "owner_public_key": "BC1YLianxEsskKYNyL959k6b6UPYtRXfZs4MF3GkbWofdoFQzZCkJRB",
    "business_name": "business",
    "email": "business@email.com",
    "headline": "Some headline",
    "social_networks": [
        {
        "slug": "linkedin",
        "link": "http://linkedin.com"
    },
    {
        "slug": "instagram",
        "link": "http:instagram.com"
    }
    ]
}

Notice that the second object inside the social_networks array has an invalid link. When I try to get past this body validation the server will present the error log as I stated on the first post to this issue.

arb commented 3 years ago

Please see my response here. I think the bug is within Joi + the schema you are trying to use. Can you try using Joi directly with the same value and schema and tell me what you get?

gpmarchi commented 3 years ago

I just did that test and this is the error message I'm getting back from Joi:


Error: Invalid input: domain must be a string
    at Object.exports.analyze (/Users/dev/Documents/Projetos/backend/node_modules/@sideway/address/lib/domain.js:21:15)
    at Object.exports.isValid (/Users/dev/Documents/Projetos/backend/node_modules/@sideway/address/lib/domain.js:101:21)
    at Object.validate (/Users/dev/Documents/Projetos/backend/node_modules/joi/lib/types/string.js:653:33)
    at Object.internals.rules (/Users/dev/Documents/Projetos/backend/node_modules/joi/lib/validator.js:394:33)
    at Object.exports.validate (/Users/dev/Documents/Projetos/backend/node_modules/joi/lib/validator.js:350:22)
    at internals.Base.$_validate (/Users/dev/Documents/Projetos/backend/node_modules/joi/lib/base.js:773:26)
    at Object.validate (/Users/dev/Documents/Projetos/backend/node_modules/joi/lib/types/keys.js:108:45)
    at Object.exports.validate (/Users/dev/Documents/Projetos/backend/node_modules/joi/lib/validator.js:325:26)
    at internals.Base.$_validate (/Users/dev/Documents/Projetos/backend/node_modules/joi/lib/base.js:773:26)
    at Object.validate (/Users/dev/Documents/Projetos/backend/node_modules/joi/lib/types/array.js:273:45)
arb commented 3 years ago

I would suggest opening an issue on the Joi repo. That schema appears valid to me according to the docs.