hapijs / joi

The most powerful data validation library for JS
Other
20.95k stars 1.51k forks source link

Issue with validating number coming as string checking range from negative value to positive #2968

Closed dev-saransh closed 1 year ago

dev-saransh commented 1 year ago

Support plan

Context

How can we help?

i am dealing with form data where i needed to validate form-data and there validate location but i end up with following error

input body

{
  contactNumber: '+911212121212',
  location: [ '200', '200' ]
}

1.

static  locationValidationSchema = Joi.array().items(
        Joi.string().max(-180).min(180).required(),
        Joi.string().max(-90).min(90).required()
    );

Error => throw new AssertError(args); ^ Error: limit must be a positive integer or reference at new module.exports (C:\Users\Dell\WebstormProjects\tcommer-backend\node_modules\@hapi\hoek\lib\error.js:23:19) at module.exports (C:\Users\Dell\WebstormProjects\tcommer-backend\node_modules\@hapi\hoek\lib\assert.js:21:11)at internals.Base.$_addRule (C:\Users\Dell\WebstormProjects\tcommer-backend\node_modules\joi\lib\base.js:609:29) at internals.length (C:\Users\Dell\WebstormProjects\tcommer-backend\node_modules\joi\lib\types\string.js:827:19) at internals.Base.method [as max] (C:\Users\Dell\WebstormProjects\tcommer-backend\node_modules\joi\lib\types\string.js:503:34) at (C:\Users\Dell\WebstormProjects\tcommer-backend\validation\user.validation.js:9:22) at Object. (C:\Users\Dell\WebstormProjects\tcommer-backend\validation\user.validation.js:5:1) at Module._compile (node:internal/modules/cjs/loader:1256:14) at Module._extensions..js (node:internal/modules/cjs/loader:1310:10) at Module.load (node:internal/modules/cjs/loader:1119:32)


2.

static  locationValidationSchema = Joi.array().items(
        Joi.number().max(-180).min(180).required(),
        Joi.number().max(-90).min(90).required()
    );

ValidationError: \"location[0]\" does not match any of the allowed types

3.

static  locationValidationSchema = Joi.array().items(
        Joi.number().greater(-180).less(180).required(),
        Joi.number().greater(-90).less(90).required()
    );

ValidationError: \"location[0]\" does not match any of the allowed types

dev-saransh commented 1 year ago

here i have tried adding some custom validation where i parse To Number

.custom(
            (value, helpers) => {
                const parsedValue = Number(value); // Attempt to convert the string to a number
                if (isNaN(parsedValue)) {
                    // If the conversion fails, return an error
                    return helpers.error('number.base', {value});
                }
                return parsedValue;
            },
            'Custom Conversion'
        )

but it has 3 possibility either use

  1. Joi.string()
    • Issue - here issue is that i can not check for negative ranged value and its gives me error
  2. Joi.number()
    • Issue - here it says unexpected type as number is coming in string form
  3. Joi.custom()
    • Issue - here no min max or greater smaller functionality available and also can not use number or string after it

I think if i want to use custom then first i have to parse string to number and then use number() then apply rules like min max or greater smaller ,but all this scenario is also impossible , its like deadlock situation

dev-saransh commented 1 year ago

Here i have tried to create minimum reproduceable code below are the code

app.js

const express = require('express');

const app = express();
const Joi = require('joi');

app.use(express.json())
app.post('/', (req, res, next) => {
    console.log(req.body);
    const schema = Joi.object({
        number : Joi.array().items(
            Joi.number().greater(-180).less(180).required(),
            Joi.number().greater(-90).less(90).required()
        )
    });
    const {error} = schema.validate(req.body);
    if (error) {
        res.status(500).send(error);
    }else{
        res.send('SUC');
    }
});

app.listen(3500,()=>{
    console.log("Listening on port 3500");
});

packege.json

{
  "name": "testingjoi",
  "version": "1.0.0",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "keywords": [],
  "description": "",
  "dependencies": {
    "express": "^4.18.2"
  }
}

Input

request Type : POST route : 'http://localhost:3500/' body :

 {
    "number": ["200","100"]
}

Output Error

{
    "_original": {
        "number": [
            "200",
            "100"
        ]
    },
    "details": [
        {
            "message": "\"number[0]\" does not match any of the allowed types",
            "path": [
                "number",
                0
            ],
            "type": "array.includes",
            "context": {
                "pos": 0,
                "value": "200",
                "label": "number[0]",
                "key": 0
            }
        }
    ]
}
Marsup commented 1 year ago

200 is over both 90 and 180, what do you expect to happen? Is it the fact that you get an error or this specific error that is the problem?

dev-saransh commented 1 year ago

this specific error is the issue @Marsup

Marsup commented 1 year ago

That's because there is no way of knowing which schema is the wrong one because they both fail validation. If those are coordinates, I think your schema should actually look like this:

Joi.array().ordered(
    Joi.number().greater(-180).less(180).required(),
    Joi.number().greater(-90).less(90).required()
)