Unable to pass custom express-validator check - javascript

The purpose of the following code is to check whether an email already exists in MongoDB, using express-validator:
app.post('/registerPage',[check('email').custom((email) => {
// connect to database
let MongoClient = require('mongodb').MongoClient;
let url = 'mongodb://localhost';
MongoClient.connect(url, function(err, client) {
if (err) throw err;
let db = client.db('Mydatabase');
// search database
return db.collection('users').findOne({
email: email
}).then(user => {
if (user) {
console.log(user); // here console shows correct record in database
return Promise.reject('E-mail already in use');
}
// otherwise, it returns null
});
})
}).withMessage('Error Message Example')], (req, res) => {
// Handle the request
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() })
}
});
When email already exists, console shows Promise.reject('E-mail already in use');.
The problem is when email does not exist, although it doesn't show Promise.reject, the code cannot process any further, validationResult(req) is not empty, so it still prints out the error message 'Error Message Example'. But there isn't any problem with non-custom validators which can successfully pass the checks.
I tried to add an else statement where !user, it doesn't work.
The question is how to pass the custom validation check, or why the array validationResult(req) is not empty even it should be? How do I make sure validationResult is empty after all checks were passed.

The issue is you are returning the promise in the callback of MongoClient.connect and not the validator function. Try using Promise wrapper like:
app.post('/registerPage',[check('email').custom((email) => {
return new Promise((resolve, reject) => {
// connect to database
let MongoClient = require('mongodb').MongoClient;
let url = 'mongodb://localhost';
MongoClient.connect(url, function(err, client) {
if (err) throw err;
let db = client.db('Mydatabase');
// search database
return db.collection('users').findOne({
email: email
}).then(user => {
if (user) {
console.log(user); // here console shows correct record in database
return reject('E-mail already in use');
}
return resolve();
});
})
});
}).withMessage('Error Message Example')], (req, res) => {
// Handle the request
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() })
}
});
Hope this helps!

Related

Unable to update database when user confirms their email

I am trying to implement email confirmation on my project. I sign a JWT which is sent in an email using nodemailer. After the link is clicked the JWT is sent to the server for processing. I am able to find out if the JWT matches the one generated by the server. However I am now struggling with updating the database to store that the user has confirmed the email.
Controller
confirmEmail = async (req, res, next) => {
this.checkValidation(req)
const { email } = req.body
const param = req.params.token
const user = await userModel.findOne({ email })
if(!user)
{
throw new HttpException(401, 'User not found')
}
if(user.confired)
{
throw new HttpException(401, 'User already confirmed')
}
if(!user.confirmed)
{
const confirmJWT = jwt.verify(param, process.env.SECRET_JWT)
if(!confirmJWT)
{
throw new HttpException(200, 'Token failed')
}
const result = await userModel.emailConfirmed(email)
throw new HttpException(401, 'User not cofirmed')
}
}
Model
emailConfirmed = async({email}) => {
const sql = `UPDATE ${this.tableName} SET confirmed = true WHERE email = ?`
const result = await query(sql, email)
return result
}
[Error] Error: Incorrect arguments to mysqld_stmt_execute
this is the error I get when attempting to change the db.

I am getting TypeError is not a function in nodeJS

I have a login route but whenever it's giving me a typeError not a function. I have checked the code too many times but still can't get why it's giving me this error:
Here's the code:
router.post("/login", async (req, res) => {
try {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).send("Please provide an email and password");
}
const user = await User.find({ email });
if (!user) return res.status(401).send("User not found");
const isMatch = await user.checkHashedPassword(password);
if (!isMatch) return res.status(401).send("Invalid credentials");
sendTokenResponse(user, 200, res);
} catch (ex) {
console.log(ex);
}
});
The error I get is that user.checkHashedPassword is not a function.
Here's the checkHashedPassword method in userSchema:
userSchema.methods.checkHashedPassword = async function (enteredPassword) {
return await bcrypt.compare(enteredPassword, this.password);
};
Here's the complete error that I get:
TypeError: user.checkHashedPassword is not a function
at D:\pythonprogs\todoapp\routes\users.js:46:32
at processTicksAndRejections (internal/process/task_queues.js:93:5)
I have checked the spellings and everything even changed the function name to see if it works but don't know why it's giving this error. Please help
problem is you are using find() method instead of findOne().
find() returns array of collections not object. try this:
const isMatch = await user[0].checkHashedPassword(password)

Get data from MongoDB query ( in Auth0 rules)

I can´t get data from my mongoDb (it´s hosted in Mlab), always returns the same error: user does not exist.
It´s a very simple query but I don´t seem to be able to get it right. My user has an email and a role in the database, so I´m trying to query based on the email and get the role.
mongo('mongodb://user:pass#data.mlab.com:port/database',
function (db) {
console.log(user.email);
var users = db.collection('users');
var result = users.findOne({email: 'email#email.com'});
var role = result.role;
What am I missing?
mongoose.Promise = global.Promise; // Promise fix if you will use mongoose
mongoose
.connect(
"mongodb://user:pass#data.mlab.com:port/database",
{ useNewUrlParser: true, useMongoClient: true }
)
.then(db => {
let dbo = db.db("database");
let query = { email: "email#email.com" };
dbo
.collection("users")
.find(query)
.toArray(function(err, result) {
if (err) throw err;
// remember it returs array
// you can map this array
// like this -> result.map(user => console.log(user.role))
console.log(result);
db.close();
});
})
.catch(console.log);
try to use mongoose and make sure you use your own promises as described here
Try this:
mongo('mongodb://user:pass#data.mlab.com:port/database', function (db) {
var users = db.collection('users');
users.findOne({email: 'email#email.com'}, , function (err, user) {
if (err) return callback(err);
if (!user) return if (!user) return callback(new WrongUsernameOrPasswordError(email)
var role = result.role;
});
You can also look into the MongoDB login template used in Custom Database connections scripts: https://auth0.com/docs/connections/database/custom-db/templates/login#mongodb

Object not defined when using await

I am currently trying to add some authentication to my node API.
Right now I'm using PassportJS (pretty new to this so sorry for my incompetents).
I am trying to add a local strategy and check if the users password is legit when loggin in:
// Local Strategy
passport.use(
new LocalStrategy(async (username, password, done) => {
try {
// Find user by username
const user = await User.findOne({ username })
// No user found
if (!user) {
return done(null, false)
}
console.log('user', user) // Getting output
// Check if password correct
const isMatch = await user.isValidPassword(password)
// Handle if password is not correct
if (!isMatch) {
return done(null, false)
}
// Return user
done(null, user)
} catch (err) {
done(err, false)
}
})
)
Something I've noticed is when using await on const isMatch = await user.isValidPassword(password) Postman is saying: Error: ReferenceError: user is not defined. And when I remove await it works fine, but I can type in the wrong password but I still can login. And I can see my user object when I console.log it.
{
"username": "martinnord3",
"password": "this_is_the_wrong_password"
}
Here's the isValidPassword function:
UserSchema.methods.isValidPassword = async function(newPassword) {
try {
return await bcrypt.compare(newPassword, user.password)
} catch (err) {
throw new Error(err)
}
}
I guess there's something obvious I'm missing, but I can't manage to solve this.
Thanks for taking your time to read this!
Well this is a bit awkward, but I guess it's my duty to answer my own dumb question... My function isValidPassword has this: ...user.password and I don't specify what user is in that function.. It expects this.

Mongoose seems to satisfy wrong promise (node js)

I am trying to refactor some inherited code. In every endpoint was the same validation code. I want to pull it out into it's own method. I am new to promises, but I think that is what I want to use. The issues is prom seems to be resolved at the User.findOne call and exits with an undefined prom.promise.
cheers
bob
function validateUser(req) {
var prom = q.defer();
var token = getToken(req.headers);
if (token) {
console.log("have a token")
var decoded = jwt.decode(token, config.secret);
console.log("now going to look for the user")
//Problem exit is on next line
User.findOne({
name: decoded.name
}, function (err, user) {
if (err) throw err;
prom.reject(err);
if (!user) {
console.log("no user found")
prom.reject("Authentication failed. User not found.")
} else {
console.log("user found returning true")
prom.resolve(true);
}
})
} else {
console.log("no token found")
prom.reject("No token provided.")
}
return prom.promise;
}
why you are using promises when mongoose itself returns it.
function validateUser(req, callback) {
var token = getToken(req.headers);
if (token) {
var decoded = jwt.decode(token, config.secret);
User.findOne({
name: decoded.name
}, function (err, user) {
if (err) throw err;
callback(err);
if (!user) {
callback("Authentication failed. User not found.")
} else {
console.log("user found returning true")
callback(null, {status:true, userData:user});
}
})
} else {
callback("No token provided.")
}
}
In above code,
if token is not found callback is returned with an error in the first attempt. if token is found then it is decoded in a row and if matched in DB if the result is an error then the callback is called with err parameter else if no user is found or empty match then a custom message is sent in callback error part. But in final is returned as success with status and userData.

Categories

Resources