express-validator wrong check - express-validator

I'm using express-validator 5.3.1. I defined password check like this :
check('password')
.not().isEmpty().withMessage('Password can\'t be null')
.isString()
.isLength({ min: 8 }),
check('retypePassword')
.not().isEmpty().withMessage('Password can\'t be null')
.isString().withMessage('Password must be a string')
.custom((value, { req }) => {
if(value.trim() !== req.body.password.trim()) {
throw new Error ('Password confirmation does not match password');
}
}),
For testing, I send same password and retypePassword ('password') and got error :
[
{
"location": "body",
"param": "retypePassword",
"value": "password",
"msg": "Invalid value"
}
]
I defined message with all error of retypePassword, so what's going on ?

When you implement a custom validation you have to return true if the validation succeed, otherwise you will get the "Invalid value" error message. So you just add a return true; statement like this
.custom((value, { req }) => {
if(value.trim() !== req.body.password.trim()) {
throw new Error ('Password confirmation does not match password');
}
return true;
})

Related

"User is not authenticated" error verifying authentication code after updating the e-mail

After I submit the verification code sent to the user's email after a email update, when I try to verify with verifyAttribute, it throws the following error: "User is not authenticated"
getUser returns a CognitoUser.
onSubmitEmailConfirmation = async (values) => {
const { code, newEmail, password } = this.state;
const { first_name, last_name, email } = this.props.data;
getSession()
.then(({ user, email }) => {
authenticate(email, password).then(() => {
getUser(email).verifyAttribute("email", code, {
onSuccess: () => {
this.props.updateUserData({
email: newEmail,
first_name: first_name,
last_name: last_name
});
this.updateNotificationMessages(
"Email verified with success!",
newEmail
);
this.openNotificationWithIcon("success");
},
onFailure: (err) => {
this.updateNotificationMessages(
"There was a error confirming your email",
err.message
);
this.openNotificationWithIcon("error");
}
});
});
})
.catch((err) => {
this.updateNotificationMessages(
"There was a error confirming your email",
err.message
);
this.openNotificationWithIcon("error");
});
};

checkSchema syntax documentation

I would like to use the checkSchema method instead of what I am currently doing with all the checks on the post route in an array. The problem I have is I can't find good documentation on the syntax used in the object for each key. The doc page for schema validation (https://express-validator.github.io/docs/schema-validation.html) gives one example but no links to all the syntax that defines all the attributes you can use (isInt, toInt, isUppercase, rtrim, etc.) I have searched high and low for the docs that tell you everything you can use there but no luck. Can someone point me in the right place?
express-validator is a set of express.js middlewares that wraps validator.js validator and sanitizer functions.
you can find all the rules available in the link above.
here is a good example how it's used with checkSchema:
import { checkSchema, validationResult } from 'express-validator'
const schema = {
id: {
isFloat: true,
// Sanitizers can go here as well
toFloat: true,
errorMessage: "must be a valid number"
},
first_name: {
exists: {
errorMessage: "first_name is required"
},
isLength: {
errorMessage: "first_name has invalid length",
options: {
min: 1
}
}
},
middle_name: {
optional: {
options: { nullable: true, checkFalsy: true }
}
},
last_name: {
exists: {
errorMessage: "last_name is required"
},
isLength: {
errorMessage: "last_name has invalid length",
options: {
min: 1
}
}
},
date_of_birth: {
isISO8601: {
errorMessage: `date of birth is not a valid iso date`
},
isBefore: {
date: "01-01-2000",
errorMessage: `should be less than 01-01-2000`
},
isAfter: {
date: "01-01-1970",
errorMessage: `should be greater than 01-01-1970`
}
},
email: {
exists: {
errorMessage: "email is required"
},
isEmail: {
errorMessage: "email is invalid"
}
},
current_country_of_residence: {
exists: {
errorMessage: "current_country_of_residence is required",
options: {
checkNull: true,
checkFalsy: true
}
}
},
current_city_of_residence: {
exists: {
bail: true,
errorMessage: "current_city_of_residence is required"
},
isMongoId: {
errorMessage: "current_city_of_residence is has invalid id for"
}
},
email: {
isEmail: { errorMessage: 'email is not a valid email' },
isLength: { errorMessage: 'email has invalid length', options: { min: 1 } }
},
skills: {
isArray: {
errorMessage: `invalid value for skills`,
options: {
min: 3,
max: 5
}
},
isIn: {
options: ["java", "C++", "javascript"],
errorMessage: `allowed values for skills are: ${["java", "C++", "javascript"]}`
},
custom: {
options: (values) => {
const unique_values = new Set(values)
if (unique_values.size !== values.length) {
return Promise.reject()
}
return Promise.resolve()
},
errorMessage: `you can't add duplicated`
},
customSanitizer: {
options: async (value, { req }) => {
return value
}
}
}
}
const validate = () => {
return [
checkSchema(schema),
(req, res, next) => {
const errors = validationResult(req)
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.mapped() })
}
next()
}
]
}
export default validate()

Issue in loopback's upsertWithWhere()

I'm using loopback3.x. Why upsertWithWhere function always updates the same instance? Only one instance is there for all the time when updateWithWhere function executes.
app.models.oneTimePassword.upsertWithWhere({
where: {
userId: user.id
}
}, {
userId: user.id,
otp: otp,
updatedAt: updatedAt,
type: 'email'
}, (err, res) => {
if (!err) {
callback(null, {
status: "OK",
message: "email sent"
});
} else {
callback(err);
}
});
app.models.oneTimePassword.upsertWithWhere(
{
userId: user.id
},
{
userId: user.id,
otp: otp,
updatedAt: updatedAt,
type: 'email'
},
(err, res) => {
if (!err) {
callback(null, {
status: "OK",
message: "email sent"
});
} else {
callback(err);
});
Try this, The first argument of upsertWithWhere should be where therefore, you don't need to add where: {} check out this official documentation

How to validate json schema using avj and postman

I'm trying to validate the following json that looks like this:
{
"errors": false,
}
using this on postman:
var Ajv = require('ajv'),
ajv = new Ajv({logger: console, coerceTypes: false}),
schema = {
"errors": {
"type": "number"
}
};
pm.test('Schema is valid', function() {
var error = pm.response.json()['errors'];
console.log("this is error: " +error);
pm.expect(ajv.validate(schema, {errors: error})).to.be.true;
});
pm.test('Schema is valid different way', function() {
var error = pm.response.json()['errors'];
console.log("this is error: " +error);
var validate = ajv.compile(schema);
pm.expect(validate(pm.response.json())).to.be.true;
});
but it's always passing, even though my errors object is a boolean and not a number. What am I doing wrong?
note: the logs look like this
this is error: false
You can check json schema using avj in Postman as follows:
var Ajv = require('ajv'),
ajv = new Ajv({logger: console}),
schema = {
"properties": {
"errors": {
"type": "boolean"
}
}
};
pm.test('Schema is valid', function() {
var error = pm.response.json()['errors'];
pm.expect(ajv.validate(schema, {errors: error})).to.be.true;
});
Data:
{
"errors": false
}
Result: Pass
Data:
{
"errors": true
}
Result: Pass
Data:
{
"errors": 123
}
Result: Fail
An alternate way
pm.test('Schema is valid', function() {
pm.expect(typeof(pm.response.json().errors) === "boolean").to.be.true;
});

before Remote in Loopback

I'm trying to use the before Remote hook in loopback to check an user token before the call of my remote method, but the thing is that I can only return a javascript Error, like these.
"error": {
"statusCode": 401,
"name": "Error",
"message": ""
}
This is the code that i'm using in the before remote.
Model.beforeRemote('method', function (context, unused, next) {
let token = Model.app.models.Token;
let id = context.args.Id;
let date = moment();
Rx.Observable.fromPromise(token.find({
where: {
and: [
{ id: id, },
{ expiration: { gt: date } }
]
}
})).subscribe((token => {
if (token.length > 0) {
next();
} else {
let err = new Error();
err.status = 401;
delete err.stack;
return next()
}
}))
});
And I need a "custom" response that isn't an error, something like these.
{
"success": false,
"data": {
"service": "self",
"operation": "rest",
"code": "unauthorized"
},
"message": "Invalid token"
}
I tried with the after Remote hook and I can change the response to get something like that, but I want to get a quicker response in the case that the token is invalid.
Is there any way to achieve this with the before hook? or I had to use after hook?
Thanks
You may want to pass the error to the next function:
return next(err)