Joi Validations: Capture the value passed in Custom Error Message - javascript

I am using Joi Library with NodeJs/Typescript for validations.
Validating a request body for a Post Operation.
I am using the language option to provide custom messages for respective field validations.
Below is the code
const bodySchema = Joi.object().keys({
// had to change from string to any so as to avoid multiple messages when empty
field1: Joi.any().required().valid('Dummy').options({
language: {
any: {
// wrt empty: specific error message not displaying with any but empty error is handled by allowOnly custom message. Anways there is no custom message for empty in requirements
// empty: '!!The parameter \'field1\' cannot be empty. It must be \'Dummy\'',
required: '!!The parameter \'field1\' is mandatory and must be the value \'Dummy\'',
allowOnly: '!!Invalid value for parameter \'field1\'. It must be \'Dummy\''
// how to capture value passed for field1 in the message?
}
}
}),
How to Capture the wrong field value passed as requestBody in the custom error message
For eg if I pass request body for the POST endpoint
{
"field1": "wrongvalue",
}
Expected custom message
Invalid value 'wrongvalue' for parameter \'field1\'. It must be \'Dummy\''
I have gone through JOI API but could not find any reference to doing this.
While regex option has the facility to capture the value passed.
{{value}} works in regex but not in other options.
Please let me know if there is a way to capture the value.

try this ......
const typeSchema = Joi.object({field1: Joi
any()
.required()
.valid('Dummy')
.error(errors => {
errors.forEach(err => {
switch (err.type) {
case "string.base":
case "required":
err.message = "field 1 is mandatory and must be the value";
break;
case "any.allowOnly":
err.message = "field1 must be Dummy";
break;
default:
console.log('validate error type missing', err.type);
break;
}
});
return errors;
}),
})

Related

How to use request body value in the .withMessage() function in express validator chain

I want to display my express validator errors with the dynamic value user entered.
For example, a user enters an invalid username (lets say "$##") pattern (I will attach my regex somewhere) I want to send my error message as a response like this :
{
"errorCode" : "234",
"field" : "username",
"value " : "$##",
"msg" : "Username : [$##] is an invalid username pattern, please check the rules for valid usernames"
}
I want to achieve this with .withMessage() in the validation chain.
My current chain code :
check('username')
.trim()
.not()
.isEmpty()
.withMessage('username can\'t be empty')
.bail()
.matches("^[a-zA-Z0-9]([._-](?![._-])|[a-zA-Z0-9]){3,18}[a-zA-Z0-9]$")
.withMessage(
{
errorCode: '234',
field : 'username',
value : ? ,
msg: 'Username : [?] is an invalid username pattern, please check the rules for valid usernames'
})
Since I can't access my req.body inside how can I achieve it?
Thanks
You can use a function to get the value from a parameter:
.withMessage((value) => { return `Invalid value: ${value}` })
Adapting that to your solution looks like this:
.withMessage(
(value) => {
return {
"errorCode": 234,
"field": 'username',
"value": value,
"msg": `Username: ${value} is an invalid username pattern, please check the rules for valid usernames`
}
})
And, if you want, you can sanitize the input value first with something like:
.escape().withMessage(...)

Raise validation when recive extra key in yup object

I am using yup for object validations. I have the following schema
const schema = yup.object().shape({
name: yup.string().required(),
});
I am validating it with object
{
"name": "Foo",
"desc": "Lorem ipsum"
}
Yup validates this object although it has an extra key desc. I want to raise the error for extra keys in the object.
I have tried with abortEarly and stripUnknown in .validate but it doesn't work.
schema.validateSync(data, { strict: true, stripUnknown: true })
You need to append the .strict() to the object you are validating. This makes the validation fail and then you can handle the error however you wish to do that.
So, in your case, change your schema to this:
const schema = yup.object().shape({
name: yup.string().required()
}).noUnknown(true).strict();
await schema.validate(data, { abortEarly: false });

Flow type: either one property is required or the other

I am trying to define a type in flow such that you must specify either a Client or an Invoice. This is my attempt at doing that:
type Client = {
client: {
id: number,
},
invoice?: {
id: number,
},
};
type Invoice = {
client?: {
id: number,
},
invoice: {
id: number,
},
};
type Props = Client | Invoice;
If client is undefined, then invoice must be defined and vice-versa.
However, when I try to access properties based on this, the flow typechecker throws errors:
function getAssignedId({client, invoice}: Props) {
return client ? client.id : invoice.id;
}
results in:
22: return client ? client.id : invoice.id;
^ Cannot get `invoice.id` because property `id` is missing in undefined [1].
References:
21: function getAssignedId({client, invoice}: Asssignement) {
^ [1]
You can try it here.
Any idea why this is happening? Is there another way to achieve this with flow?
When you do deconstruct the type via:
{client, invoice}: Props
the types of those variables are resolved. client and invoice both are resolved as ?{ id: number } since they may or may not exist at the time. The typechecker does not remember that these two objects are linked, because you have separated them.
If you don't separate them, flow can keep track of the union type and do the right thing.
function getAssignedId(obj: Props) {
return obj.client ? obj.client.id : obj.invoice.id;
}
Try flow link
You are not checking if invoice is defined. If you add the check it will not throw the error

Joi custom error message works but can't display the message properly

guys.
I am trying to validate email format by using Joi and really new to coding.
By using the following syntax, it works for me to display custom error messages.
However, the result only showed the "invalid email format" and never showed "cannot be an empty field" even I left the input empty.
schema = Joi.object().keys({
email: Joi.string()
.empty()
.email()
.error(errors => {
errors.forEach(err => {
switch (err.type) {
case "any.empty":
err.message = `cannot be an empty field`;
break;
case "string.email":
err.message = `invalid email format`;
break;
default:
break;
}
});
return errors;
})
});
Thanks in advance. Cheers!

Password confirmation and password are equal but validation is still triggering JOI in React component

I creating a register form and the problems accurs while try validating password confirmation. I am using the last version of JOI-Browser.
I tried the code below and the validation error was triggered even though password and password confirmation have the same values.
password: Joi.string()
.min(5)
.required(),
passwordConfirmation: Joi.ref("password")
Here is my state object:
password: "12345"
passwordConfirmation: "12345"
username: ""
errors: {…}
passwordConfirmation: "\"passwordConfirmation\" must be one of [ref:password]"
I passed several hours trying several approaches and reading the documentation, but still no luck, the validation is still triggering,
I have other validations in this form and they work fine.
I don't think Joi.ref should be used that way.
I usually tend to do this way:
const passwordConfirmation = Joi.string()
.required()
.valid(Joi.ref('password'))
.options({
language: {
any: {
allowOnly: '!!Passwords do not match',
}
}
})
If you refer to the docs, you will see:
Note that references can only be used where explicitly supported such as in valid() or invalid() rules. If upwards (parents) references are needed, use object.assert().
If anyone has encountered a similar problem, this is the solution I have used:
validateProperty = (input) => {
let obj = { [input.name]: input.value };
let schema = { [input.name]: this.schema[input.name] };
if (input.name.endsWith("_confirm")) {
const dependentInput = input.name.substring(
0,
input.name.indexOf("_confirm")
);
obj[dependentInput] = this.state.data[dependentInput];
schema[dependentInput] = this.schema[dependentInput];
}
const { error } = Joi.validate(obj, schema);
return error ? error.details[0].message : null;
};
In my case, I have looked for _confirm because I have the field names as password and password_confirm. You need to make changes here as per your requirements.
Main logic, you just need to add value and schema of password when you are validating password_confirm
I find out what was happening. My code above was right, the problem was in my validate function.
Gabriele's Petrioli comment help me out. this is the function that cause me problems:
validateProperty = ({ name: propertyName, value }) => {
const obj = { [propertyName]: value };
const schema = { [propertyName]: this.schema[propertyName] };
const { error } = Joi.validate(obj, schema);
return error ? error.details[0].message : null;};
Has you can see i tried validate each property individually, so i can make the form more dynamic.
This trigger the validation error because when i try to validate confirmPassword there was no value in password because i passed only the value the correspond to confirmaPassword, it also needed the password value to make the comparison.
Rookie mistake

Categories